package com.example.roadeyeserver.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.roadeyeserver.constant.ProjectConstant;
import com.example.roadeyeserver.entity.*;
import com.example.roadeyeserver.entity.report.*;
import com.example.roadeyeserver.entity.request.*;
import com.example.roadeyeserver.entity.vo.GantryHourFlowWideVO;
import com.example.roadeyeserver.entity.vo.HolidayVO;
import com.example.roadeyeserver.entity.vo.RoadFlowCalculateVO;
import com.example.roadeyeserver.enums.CarTypeEnum;
import com.example.roadeyeserver.enums.HolidayEnum;
import com.example.roadeyeserver.mapper.GantryHourFlowWideMapper;
import com.example.roadeyeserver.result.Result;
import com.example.roadeyeserver.service.*;
import com.example.roadeyeserver.util.DateTimeUtil;
import com.example.roadeyeserver.util.QueryUtil;
import com.example.roadeyeserver.util.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GantryHourFlowWideServiceImpl extends ServiceImpl<GantryHourFlowWideMapper, GantryHourFlowWide> implements GantryHourFlowWideService {

    @Resource
    private GantryHourFlowWideMapper gantryHourFlowWideMapper;

    @Resource
    private AMjHxlService aMjHxlService;

    @Resource
    private GantryRoadAreaInfoService gantryRoadAreaInfoService;

    @Resource
    private StationRoadAreaInfoService stationRoadAreaInfoService;

    @Resource
    private TobjTollStationInfoService tobjTollStationInfoService;

    @Resource
    private HolidayInfoService holidayInfoService;

    @Override
    public Result<CrossOverviewReport> getCrossOverviewReport(CommonRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 按请求查询数据
        GantryHourFlowWideVO gantryHourFlowWideVO = gantryHourFlowWideMapper.getCrossOverviewReport(request);
        if (gantryHourFlowWideVO == null) {
            return ResultUtil.success(new CrossOverviewReport());
        }
        CrossOverviewReport report = new CrossOverviewReport();
        // 总流量
        Integer totalFlow =
                gantryHourFlowWideVO.getVhc1() +
                gantryHourFlowWideVO.getVhc2() +
                gantryHourFlowWideVO.getVhc3() +
                gantryHourFlowWideVO.getVhc4() +
                gantryHourFlowWideVO.getVhc11() +
                gantryHourFlowWideVO.getVhc12() +
                gantryHourFlowWideVO.getVhc13() +
                gantryHourFlowWideVO.getVhc14() +
                gantryHourFlowWideVO.getVhc15() +
                gantryHourFlowWideVO.getVhc16();
        // 客车流量
        Integer busFlow =
                gantryHourFlowWideVO.getVhc1() +
                gantryHourFlowWideVO.getVhc2() +
                gantryHourFlowWideVO.getVhc3() +
                gantryHourFlowWideVO.getVhc4();
        // 货车流量
        Integer truckFlow =
                gantryHourFlowWideVO.getVhc11() +
                gantryHourFlowWideVO.getVhc12() +
                gantryHourFlowWideVO.getVhc13() +
                gantryHourFlowWideVO.getVhc14() +
                gantryHourFlowWideVO.getVhc15() +
                gantryHourFlowWideVO.getVhc16();
        report.setTotalFlow(totalFlow);
        report.setTruckFlow(truckFlow);
        report.setBusFlow(busFlow);
        // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
        report.setVhc1(gantryHourFlowWideVO.getVhc1());
        report.setVhc2(gantryHourFlowWideVO.getVhc2());
        report.setVhc3(gantryHourFlowWideVO.getVhc3());
        report.setVhc4(gantryHourFlowWideVO.getVhc4());
        report.setVhc11(gantryHourFlowWideVO.getVhc11());
        report.setVhc12(gantryHourFlowWideVO.getVhc12());
        report.setVhc13(gantryHourFlowWideVO.getVhc13());
        report.setVhc14(gantryHourFlowWideVO.getVhc14());
        report.setVhc15(gantryHourFlowWideVO.getVhc15());
        report.setVhc16(gantryHourFlowWideVO.getVhc16());
        report.setVhc21(gantryHourFlowWideVO.getVhc21());
        report.setVhc22(gantryHourFlowWideVO.getVhc22());
        report.setVhc23(gantryHourFlowWideVO.getVhc23());
        report.setVhc24(gantryHourFlowWideVO.getVhc24());
        report.setVhc25(gantryHourFlowWideVO.getVhc25());
        report.setVhc26(gantryHourFlowWideVO.getVhc26());
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(report);
        }
        CarTypeEnum.calculateAndSetObjectFlow(carTypeChoose, report);
        return ResultUtil.success(report);
    }

    @Override
    public Result<List<RoadFlowReport>> getRoadFlowReport(CommonRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 门架
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-道路名称映射
        Map<String, String> roadCodeNameMap = this.getRoadCodeNameMap();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 按请求查询数据(查询精确到门架)
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
        if (CollectionUtil.isEmpty(records)) {
            return ResultUtil.success(new ArrayList<>());
        }
        List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TOTAL_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> roadFlowMap = calculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        // 返回列表
        List<RoadFlowReport> reports = new ArrayList<>();
        roadFlowMap.forEach((roadCode, flowList) -> {
            RoadFlowReport report = new RoadFlowReport();
            report.setRoadCode(roadCode);
            // 路段信息实体类
            String roadName = roadCodeNameMap.get(roadCode);
            report.setRoadName(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = flowList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = flowList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int roadFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int roadFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadFlow = roadFlowUp + roadFlowDown;
            report.setTotalFlow(roadFlow);
            reports.add(report);
        });
        return ResultUtil.success(reports);
    }

    @Override
    public Result<List<TrafficRankReport>> getTrafficRankReport(CommonRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 按请求查询数据
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getTrafficRankReport(request);
        // 返回列表
        List<TrafficRankReport> reports = new ArrayList<>();
        records.forEach(record -> {
            // 判断reports中是否已经存在该起止门架
            if (this.isExit(reports, record)) {
                TrafficRankReport report = this.getExitReportItem(reports, record);
                // 客车累计流量 = 原客车车累计流量 + 1234型客车流量
                report.setBusFlow(report.getBusFlow() + record.getVhc1() + record.getVhc2() + record.getVhc3() + record.getVhc4());
                // 货车累计流量 = 原货车车累计流量 + 123456型货车流量
                report.setTruckFlow(report.getTruckFlow() + record.getVhc11() + record.getVhc12() + record.getVhc13() + record.getVhc14() + record.getVhc15() + record.getVhc16());
                // 总流量 = 货车累计流量 + 客车累计流量
                report.setTotalFlow(report.getBusFlow() + report.getTruckFlow());
                // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                report.setVhc1(record.getVhc1() + report.getVhc1());
                report.setVhc2(record.getVhc2() + report.getVhc2());
                report.setVhc3(record.getVhc3() + report.getVhc3());
                report.setVhc4(record.getVhc4() + report.getVhc4());
                report.setVhc11(record.getVhc11() + report.getVhc11());
                report.setVhc12(record.getVhc12() + report.getVhc12());
                report.setVhc13(record.getVhc13() + report.getVhc13());
                report.setVhc14(record.getVhc14() + report.getVhc14());
                report.setVhc15(record.getVhc15() + report.getVhc15());
                report.setVhc16(record.getVhc16() + report.getVhc16());
                report.setVhc21(record.getVhc21() + report.getVhc21());
                report.setVhc22(record.getVhc22() + report.getVhc22());
                report.setVhc23(record.getVhc23() + report.getVhc23());
                report.setVhc24(record.getVhc24() + report.getVhc24());
                report.setVhc25(record.getVhc25() + report.getVhc25());
                report.setVhc26(record.getVhc26() + report.getVhc26());
            } else {
                this.createReportItem(reports, record);
            }
        });
        // 对reports按照总流量降序进行排序
        reports.sort(Comparator.comparingInt(TrafficRankReport::getTotalFlow).reversed());
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(reports);
        }
        CarTypeEnum.calculateAndSetListFlow(carTypeChoose, reports);
        return ResultUtil.success(reports);
    }

    @Override
    public Result<List<RoadRankReport>> getRoadRankReport(CommonRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 门架
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-道路名称映射
        Map<String, String> roadCodeNameMap = this.getRoadCodeNameMap();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 按请求查询数据(查询精确到门架)
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
        if (records.isEmpty()) {
            return ResultUtil.success(new ArrayList<>());
        }
        // 计算总流量
        List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TOTAL_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> totalFlowMap = calculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        // 计算客车流量
        List<RoadFlowCalculateVO> calculateBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.BUS_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> busFlowMap = calculateBusList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        // 计算货车流量
        List<RoadFlowCalculateVO> calculateTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TRUCK_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> trunkFlowMap = calculateTruckList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        // 返回列表
        List<RoadRankReport> reports = new ArrayList<>();
        // 处理总流量
        totalFlowMap.forEach((roadCode, flowList) -> {
            RoadRankReport report = new RoadRankReport();
            report.setRoad(roadCode);
            // 路段信息实体类
            String roadName = roadCodeNameMap.get(roadCode);
            report.setRoadName(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = flowList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = flowList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int roadTotalFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int roadTotalFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int totalFlow = roadTotalFlowUp + roadTotalFlowDown;
            report.setTotalFlow(totalFlow);
            reports.add(report);
        });
        // 处理客车流量
        busFlowMap.forEach((roadCode, flowList) -> {
            for(RoadRankReport report : reports) {
                // 路段编码对应
                if (roadCode.equals(report.getRoad())) {
                    // 上行列表
                    List<RoadFlowCalculateVO> upFlowList = flowList.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 下行列表
                    List<RoadFlowCalculateVO> downFlowList = flowList.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站直接的客车上行流量
                    int roadBusFlowUp = this.calculateRoadFlow(upFlowList);
                    // 计算收费站直接的客车下行流量
                    int roadBusFlowDown = this.calculateRoadFlow(downFlowList);
                    report.setBusFlow(roadBusFlowUp + roadBusFlowDown);
                }
            }
        });
        // 处理货车流量
        trunkFlowMap.forEach((roadCode, flowList) -> {
            for(RoadRankReport report : reports) {
                // 路段编码对应
                if (roadCode.equals(report.getRoad())) {
                    // 上行列表
                    List<RoadFlowCalculateVO> upFlowList = flowList.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 下行列表
                    List<RoadFlowCalculateVO> downFlowList = flowList.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站直接的货车车上行流量
                    int roadTruckFlowUp = this.calculateRoadFlow(upFlowList);
                    // 计算收费站直接的货车cline行流量
                    int roadTruckFlowDown = this.calculateRoadFlow(downFlowList);
                    report.setTruckFlow(roadTruckFlowUp + roadTruckFlowDown);
                }
            }
        });
        return ResultUtil.success(reports);
    }

    @Override
    public Result<List<CrossOverviewStatisticReport>> getCrossOverviewStatisticReport(CrossOverviewStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 起止门架不能为空
        String startEndPlace = request.getStartEndPlace();
        if (StringUtils.isEmpty(startEndPlace)) {
            return ResultUtil.fail("起止门架不能为空!");
        }
        // 统计类型不能为空
        String statisticType = request.getStatisticType();
        if (StringUtils.isEmpty(statisticType)) {
            return ResultUtil.fail("统计类型不能为空!");
        }
        // -之前的门架
        String firstPlace = startEndPlace.split(ProjectConstant.MINUS)[0];
        // -之后的门架
        String lastPlace = startEndPlace.split(ProjectConstant.MINUS)[1];
        List<String> places = new ArrayList<>();
        places.add(firstPlace);
        places.add(lastPlace);
        // 查询两个收费站之间所属的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .in(AMjHxl::getStartPlace, places)
                .in(AMjHxl::getEndPlace, places)
        );
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 返回列表
        List<CrossOverviewStatisticReport> result = new ArrayList<>();
        if (ProjectConstant.DIRECTION.equals(statisticType)) {
            // 上行列表
            List<AMjHxl> upGantryList = list.stream().filter(aMjHxl -> aMjHxl.getFx().equals(ProjectConstant.UP)).collect(Collectors.toList());
            // 下行列表
            List<AMjHxl> downGantryList = list.stream().filter(aMjHxl -> aMjHxl.getFx().equals(ProjectConstant.DOWN)).collect(Collectors.toList());
            // 查询上行数据
            CrossOverviewStatisticRequest upRequest = BeanUtil.copyProperties(request, CrossOverviewStatisticRequest.class);
            upRequest.setGantryIds(upGantryList.stream().map(AMjHxl::getMjid).collect(Collectors.toList()));
            List<GantryHourFlowWideVO> upList = gantryHourFlowWideMapper.getFlow(upRequest);
            // 查询下行数据
            CrossOverviewStatisticRequest downRequest = BeanUtil.copyProperties(request, CrossOverviewStatisticRequest.class);
            downRequest.setGantryIds(downGantryList.stream().map(AMjHxl::getMjid).collect(Collectors.toList()));
            List<GantryHourFlowWideVO> downList = gantryHourFlowWideMapper.getFlow(downRequest);
            // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
            String timeType = request.getTimeType();
            // 根据开始时间、结束时间、时间类型生成时间点列表
            List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
            // 遍历时间点列表并获取对应的数据
            for (int i = 0; i < timePointList.size() - 1; i++) {
                CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
                // 当前时间点
                String timePoint = timePointList.get(i);
                Date timePointDate = DateUtil.parse(timePoint);
                // 下一个时间点
                String nextTimePoint = timePointList.get(i + 1);
                Date nextTimePointDate = DateUtil.parse(nextTimePoint);
                // 时间点
                String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
                report.setTimePoint(timePointDisplay);
                // 这个时间段内的上行流量数据(大于等于timePoint,小于nextTimePoint)
                int upTotalFlow = 0;
                if (CollectionUtil.isNotEmpty(upList)) {
                    List<GantryHourFlowWideVO> upItemList = upList.stream()
                            .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                            .collect(Collectors.toList());
                    // 上行总流量
                    upTotalFlow = upItemList.stream()
                            .mapToInt(item ->
                                    item.getVhc1() + item.getVhc2() + item.getVhc3() + item.getVhc4() +
                                    item.getVhc11() + item.getVhc12() + item.getVhc13() + item.getVhc14() + item.getVhc15() + item.getVhc16())
                            .sum();
                    // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                    report.setUpVhc1(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum());
                    report.setUpVhc2(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum());
                    report.setUpVhc3(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum());
                    report.setUpVhc4(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum());
                    report.setUpVhc11(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum());
                    report.setUpVhc12(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum());
                    report.setUpVhc13(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum());
                    report.setUpVhc14(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum());
                    report.setUpVhc15(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum());
                    report.setUpVhc16(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum());
                    report.setUpVhc21(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum());
                    report.setUpVhc22(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum());
                    report.setUpVhc23(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum());
                    report.setUpVhc24(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum());
                    report.setUpVhc25(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum());
                    report.setUpVhc26(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum());
                }
                // 这个时间段内的下行流量数据(大于等于timePoint,小于nextTimePoint)
                int downTotalFlow = 0;
                if (CollectionUtil.isNotEmpty(downList)) {
                    List<GantryHourFlowWideVO> downItemList = downList.stream()
                            .filter(item -> item.getTime() != null &&  item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                            .collect(Collectors.toList());
                    // 下行总流量
                    downTotalFlow = downItemList.stream()
                            .mapToInt(item ->
                                    item.getVhc1() + item.getVhc2() + item.getVhc3() + item.getVhc4() +
                                    item.getVhc11() + item.getVhc12() + item.getVhc13() + item.getVhc14() + item.getVhc15() + item.getVhc16())
                            .sum();
                    // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                    report.setDownVhc1(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum());
                    report.setDownVhc2(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum());
                    report.setDownVhc3(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum());
                    report.setDownVhc4(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum());
                    report.setDownVhc11(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum());
                    report.setDownVhc12(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum());
                    report.setDownVhc13(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum());
                    report.setDownVhc14(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum());
                    report.setDownVhc15(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum());
                    report.setDownVhc16(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum());
                    report.setDownVhc21(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum());
                    report.setDownVhc22(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum());
                    report.setDownVhc23(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum());
                    report.setDownVhc24(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum());
                    report.setDownVhc25(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum());
                    report.setDownVhc26(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum());
                }
                // 总流量
                Integer totalFlow = upTotalFlow + downTotalFlow;
                report.setUpFlow(upTotalFlow);
                report.setDownFlow(downTotalFlow);
                report.setTotalFlow(totalFlow);
                result.add(report);
            }
        } else if (ProjectConstant.CAR_TYPE.equals(statisticType)) {
            // 查询数据
            request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
            List<GantryHourFlowWideVO> flowList = gantryHourFlowWideMapper.getFlow(request);
            // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
            String timeType = request.getTimeType();
            // 根据开始时间、结束时间、时间类型生成时间点列表
            List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
            // 遍历时间点列表并获取对应的数据
            for (int i = 0; i < timePointList.size() - 1; i++) {
                CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
                // 当前时间点
                String timePoint = timePointList.get(i);
                Date timePointDate = DateUtil.parse(timePoint);
                // 下一个时间点
                String nextTimePoint = timePointList.get(i + 1);
                Date nextTimePointDate = DateUtil.parse(nextTimePoint);
                // 时间点
                String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
                report.setTimePoint(timePointDisplay);
                int busFlow = 0;
                int truckFlow = 0;
                int containerFlow = 0;
                // 这个时间段内的流量数据(大于等于timePoint,小于nextTimePoint)
                if (CollectionUtil.isNotEmpty(flowList)) {
                    List<GantryHourFlowWideVO> carFlowList = flowList.stream()
                            .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                            .collect(Collectors.toList());
                    // 客车总流量
                    busFlow = carFlowList.stream()
                            .mapToInt(item -> item.getVhc1() + item.getVhc2() + item.getVhc3() + item.getVhc4()).sum();
                    // 货车总流量
                    truckFlow = carFlowList.stream()
                            .mapToInt(item -> item.getVhc11() + item.getVhc12() + item.getVhc13() + item.getVhc14() + item.getVhc15() + item.getVhc16()).sum();
                    // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                    report.setVhc1(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum());
                    report.setVhc2(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum());
                    report.setVhc3(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum());
                    report.setVhc4(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum());
                    report.setVhc11(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum());
                    report.setVhc12(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum());
                    report.setVhc13(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum());
                    report.setVhc14(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum());
                    report.setVhc15(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum());
                    report.setVhc16(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum());
                    report.setVhc21(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum());
                    report.setVhc22(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum());
                    report.setVhc23(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum());
                    report.setVhc24(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum());
                    report.setVhc25(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum());
                    report.setVhc26(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum());
                }
                report.setBusFlow(busFlow);
                report.setTruckFlow(truckFlow);
                report.setContainerFlow(containerFlow);
                int totalFlow = busFlow + truckFlow + containerFlow;
                report.setTotalFlow(totalFlow);
                result.add(report);
            }
        }
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(result);
        }
        CarTypeEnum.calculateAndSetObjectFlowUpDownListFlow(carTypeChoose, result);
        return ResultUtil.success(result);
    }

    @Override
    public Result<List<CrossOverviewStatisticReport>> getRoadStatisticReport(RoadStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 路段不能为空
        String road = request.getRoad();
        if (StringUtils.isEmpty(road)) {
            return ResultUtil.fail("路段不能为空!");
        }
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 门架
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 查询该路段拥有的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .eq(AMjHxl::getRoad, road)
        );
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 查询初始数据
        List<GantryHourFlowWideVO> flowList = gantryHourFlowWideMapper.getRoadFlowDetail(request);
        // 上行列表
        List<GantryHourFlowWideVO> upList = flowList.stream()
                .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                .collect(Collectors.toList());
        // 下行列表
        List<GantryHourFlowWideVO> downList = flowList.stream()
                .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                .collect(Collectors.toList());
        // 返回列表
        List<CrossOverviewStatisticReport> reports = new ArrayList<>();

        // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
        String timeType = request.getTimeType();
        // 根据开始时间、结束时间、时间类型生成时间点列表
        List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
        // 遍历时间点列表并获取对应的数据
        for (int i = 0; i < timePointList.size() - 1; i++) {
            // 客车流量
            int busFlow = 0;
            // 货车流量
            int truckFlow = 0;
            CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
            // 当前时间点
            String timePoint = timePointList.get(i);
            Date timePointDate = DateUtil.parse(timePoint);
            // 下一个时间点
            String nextTimePoint = timePointList.get(i + 1);
            Date nextTimePointDate = DateUtil.parse(nextTimePoint);
            // 时间点
            String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
            report.setTimePoint(timePointDisplay);
            // 这个时间段内的上行流量数据(大于等于timePoint,小于nextTimePoint)
            if (CollectionUtil.isNotEmpty(upList)) {
                List<GantryHourFlowWideVO> upItemList = upList.stream()
                        .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                        .collect(Collectors.toList());
                // 对上行流量数据进行处理(相同门架的数据对应的字段进行累加,保证一个门架只有一条数据)
                List<GantryHourFlowWideVO> upSumList = new ArrayList<>();
                for (GantryHourFlowWideVO item : upItemList) {
                    if (CollectionUtil.isEmpty(upSumList)) {
                        upSumList.add(item);
                    } else {
                        // 判断是否存在相同门架的数据
                        GantryHourFlowWideVO gantryHourFlowWideVO = upSumList.stream()
                                .filter(sumItem -> item.getGrantryId().equals(sumItem.getGrantryId()))
                                .findFirst()
                                .orElse(null);
                        if (gantryHourFlowWideVO != null) {
                            // 如果已经存在该门架数据,则对对应字段进行累加
                            gantryHourFlowWideVO.setVhc1(gantryHourFlowWideVO.getVhc1() + item.getVhc1());
                            gantryHourFlowWideVO.setVhc2(gantryHourFlowWideVO.getVhc2() + item.getVhc2());
                            gantryHourFlowWideVO.setVhc3(gantryHourFlowWideVO.getVhc3() + item.getVhc3());
                            gantryHourFlowWideVO.setVhc4(gantryHourFlowWideVO.getVhc4() + item.getVhc4());
                            gantryHourFlowWideVO.setVhc11(gantryHourFlowWideVO.getVhc11() + item.getVhc11());
                            gantryHourFlowWideVO.setVhc12(gantryHourFlowWideVO.getVhc12() + item.getVhc12());
                            gantryHourFlowWideVO.setVhc13(gantryHourFlowWideVO.getVhc13() + item.getVhc13());
                            gantryHourFlowWideVO.setVhc14(gantryHourFlowWideVO.getVhc14() + item.getVhc14());
                            gantryHourFlowWideVO.setVhc15(gantryHourFlowWideVO.getVhc15() + item.getVhc15());
                            gantryHourFlowWideVO.setVhc16(gantryHourFlowWideVO.getVhc16() + item.getVhc16());
                        } else {
                            // 如果不存在该门架,则直接添加数据
                            upSumList.add(item);
                        }
                    }
                }
                // 上行总流量
                List<RoadFlowCalculateVO> calculateUpTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, ProjectConstant.TOTAL_FLOW);
                int upFlow = this.calculateRoadFlow(calculateUpTotalList);
                report.setUpFlow(upFlow);
                // 客车上行流量
                List<RoadFlowCalculateVO> calculateUpBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, ProjectConstant.BUS_FLOW);
                busFlow += this.calculateRoadFlow(calculateUpBusList);
                // 货车上行流量
                List<RoadFlowCalculateVO> calculateUpTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, ProjectConstant.TRUCK_FLOW);
                truckFlow += this.calculateRoadFlow(calculateUpTruckList);
            }
            // 这个时间段内的下行流量数据(大于等于timePoint,小于nextTimePoint)
            if (CollectionUtil.isNotEmpty(downList)) {
                List<GantryHourFlowWideVO> downItemList = downList.stream()
                        .filter(item -> item.getTime() != null &&  item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                        .collect(Collectors.toList());
                // 对上行流量数据进行处理(相同门架的数据对应的字段进行累加,保证一个门架只有一条数据)
                List<GantryHourFlowWideVO> downSumList = new ArrayList<>();
                for (GantryHourFlowWideVO item : downItemList) {
                    if (CollectionUtil.isEmpty(downSumList)) {
                        downSumList.add(item);
                    } else {
                        // 判断是否存在相同门架的数据
                        GantryHourFlowWideVO gantryHourFlowWideVO = downSumList.stream()
                                .filter(sumItem -> item.getGrantryId().equals(sumItem.getGrantryId()))
                                .findFirst()
                                .orElse(null);
                        if (gantryHourFlowWideVO != null) {
                            // 如果已经存在该门架数据,则对对应字段进行累加
                            gantryHourFlowWideVO.setVhc1(gantryHourFlowWideVO.getVhc1() + item.getVhc1());
                            gantryHourFlowWideVO.setVhc2(gantryHourFlowWideVO.getVhc2() + item.getVhc2());
                            gantryHourFlowWideVO.setVhc3(gantryHourFlowWideVO.getVhc3() + item.getVhc3());
                            gantryHourFlowWideVO.setVhc4(gantryHourFlowWideVO.getVhc4() + item.getVhc4());
                            gantryHourFlowWideVO.setVhc11(gantryHourFlowWideVO.getVhc11() + item.getVhc11());
                            gantryHourFlowWideVO.setVhc12(gantryHourFlowWideVO.getVhc12() + item.getVhc12());
                            gantryHourFlowWideVO.setVhc13(gantryHourFlowWideVO.getVhc13() + item.getVhc13());
                            gantryHourFlowWideVO.setVhc14(gantryHourFlowWideVO.getVhc14() + item.getVhc14());
                            gantryHourFlowWideVO.setVhc15(gantryHourFlowWideVO.getVhc15() + item.getVhc15());
                            gantryHourFlowWideVO.setVhc16(gantryHourFlowWideVO.getVhc16() + item.getVhc16());
                        } else {
                            // 如果不存在该门架,则直接添加数据
                            downSumList.add(item);
                        }
                    }
                }
                // 下行总流量
                List<RoadFlowCalculateVO> calculateDownTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, ProjectConstant.TOTAL_FLOW);
                int downFlow = this.calculateRoadFlow(calculateDownTotalList);
                report.setDownFlow(downFlow);
                // 客车下行流量
                List<RoadFlowCalculateVO> calculateDownBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, ProjectConstant.BUS_FLOW);
                busFlow += this.calculateRoadFlow(calculateDownBusList);
                // 货车下行流量
                List<RoadFlowCalculateVO> calculateDownTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, ProjectConstant.TRUCK_FLOW);
                truckFlow += this.calculateRoadFlow(calculateDownTruckList);
            }
            // 客车流量
            report.setBusFlow(busFlow);
            // 货车流量
            report.setTruckFlow(truckFlow);
            // 总流量
            report.setTotalFlow(busFlow + truckFlow);
            reports.add(report);
        }
        return ResultUtil.success(reports);
    }

    @Override
    public Result<GantryHourFlowWideVO> getGantryHourFlowWideList(CrossOverviewStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 起止门架不能为空
        String startEndPlace = request.getStartEndPlace();
        if (StringUtils.isEmpty(startEndPlace)) {
            return ResultUtil.fail("起止门架不能为空!");
        }
        // -之前的门架
        String firstPlace = startEndPlace.split(ProjectConstant.MINUS)[0];
        // -之后的门架
        String lastPlace = startEndPlace.split(ProjectConstant.MINUS)[1];
        List<String> places = new ArrayList<>();
        places.add(firstPlace);
        places.add(lastPlace);
        // 查询两个收费站之间所属的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .in(AMjHxl::getStartPlace, places)
                .in(AMjHxl::getEndPlace, places)
        );
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 设置门架id
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 按请求查询数据
        GantryHourFlowWideVO result = gantryHourFlowWideMapper.getCrossOverviewReportWithDirection(request);
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(result);
        }
        CarTypeEnum.setCarTypeObjectFLow(carTypeChoose, result);
        return ResultUtil.success(result);
    }

    @Override
    public Result<GantryHourFlowWideVO> getRoadFlowList(RoadStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 道路不能为空
        String road = request.getRoad();
        if (StringUtils.isEmpty(road)) {
            return ResultUtil.fail("道路不能为空!");
        }
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 门架
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 查询这个路段所包含的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .eq(AMjHxl::getRoad, road)
        );
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 设置门架id
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 按请求查询数据(查询精确到门架)
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
        GantryHourFlowWideVO result = new GantryHourFlowWideVO();
        if (records.isEmpty()) {
            return ResultUtil.success(result);
        }
        // 上行数据
        List<GantryHourFlowWideVO> upRecords = records.stream()
                .filter(record -> ProjectConstant.UP.equals(record.getDirection()))
                .collect(Collectors.toList());
        // 下行数据
        List<GantryHourFlowWideVO> downRecords = records.stream()
                .filter(record -> ProjectConstant.DOWN.equals(record.getDirection()))
                .collect(Collectors.toList());
        // 1型客车
        List<RoadFlowCalculateVO> calculateBus1UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC1.getField());
        int bus1UpFlow = this.calculateRoadFlow(calculateBus1UpList);
        List<RoadFlowCalculateVO> calculateBus1DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC1.getField());
        int bus1DownFlow = this.calculateRoadFlow(calculateBus1DownList);
        int bus1Flow = bus1UpFlow + bus1DownFlow;
        result.setVhc1(bus1Flow);
        // 2型客车
        List<RoadFlowCalculateVO> calculateBus2UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC2.getField());
        int bus2UpFlow = this.calculateRoadFlow(calculateBus2UpList);
        List<RoadFlowCalculateVO> calculateBus2DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC2.getField());
        int bus2DownFlow = this.calculateRoadFlow(calculateBus2DownList);
        int bus2Flow = bus2UpFlow + bus2DownFlow;
        result.setVhc2(bus2Flow);
        // 3型客车
        List<RoadFlowCalculateVO> calculateBus3UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC3.getField());
        int bus3UpFlow = this.calculateRoadFlow(calculateBus3UpList);
        List<RoadFlowCalculateVO> calculateBus3DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC3.getField());
        int bus3DownFlow = this.calculateRoadFlow(calculateBus3DownList);
        int bus3Flow = bus3UpFlow + bus3DownFlow;
        result.setVhc3(bus3Flow);
        // 4型客车
        List<RoadFlowCalculateVO> calculateBus4UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC4.getField());
        int bus4UpFlow = this.calculateRoadFlow(calculateBus4UpList);
        List<RoadFlowCalculateVO> calculateBus4DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC4.getField());
        int bus4DownFlow = this.calculateRoadFlow(calculateBus4DownList);
        int bus4Flow = bus4UpFlow + bus4DownFlow;
        result.setVhc4(bus4Flow);
        // 1型货车
        List<RoadFlowCalculateVO> calculateTrunk1UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC11.getField());
        int trunk1UpFlow = this.calculateRoadFlow(calculateTrunk1UpList);
        List<RoadFlowCalculateVO> calculateTrunk1DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC11.getField());
        int trunk1DownFlow = this.calculateRoadFlow(calculateTrunk1DownList);
        int trunk1Flow = trunk1UpFlow + trunk1DownFlow;
        result.setVhc11(trunk1Flow);
        // 2型货车
        List<RoadFlowCalculateVO> calculateTrunk2UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC12.getField());
        int trunk2UpFlow = this.calculateRoadFlow(calculateTrunk2UpList);
        List<RoadFlowCalculateVO> calculateTrunk2DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC12.getField());
        int trunk2DownFlow = this.calculateRoadFlow(calculateTrunk2DownList);
        int trunk2Flow = trunk2UpFlow + trunk2DownFlow;
        result.setVhc12(trunk2Flow);
        // 3型货车
        List<RoadFlowCalculateVO> calculateTrunk3UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC13.getField());
        int trunk3UpFlow = this.calculateRoadFlow(calculateTrunk3UpList);
        List<RoadFlowCalculateVO> calculateTrunk3DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC13.getField());
        int trunk3DownFlow = this.calculateRoadFlow(calculateTrunk3DownList);
        int trunk3Flow = trunk3UpFlow + trunk3DownFlow;
        result.setVhc13(trunk3Flow);
        // 4型货车
        List<RoadFlowCalculateVO> calculateTrunk4UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC14.getField());
        int trunk4UpFlow = this.calculateRoadFlow(calculateTrunk4UpList);
        List<RoadFlowCalculateVO> calculateTrunk4DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC14.getField());
        int trunk4DownFlow = this.calculateRoadFlow(calculateTrunk4DownList);
        int trunk4Flow = trunk4UpFlow + trunk4DownFlow;
        result.setVhc14(trunk4Flow);
        // 5型货车
        List<RoadFlowCalculateVO> calculateTrunk5UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC15.getField());
        int trunk5UpFlow = this.calculateRoadFlow(calculateTrunk5UpList);
        List<RoadFlowCalculateVO> calculateTrunk5DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC15.getField());
        int trunk5DownFlow = this.calculateRoadFlow(calculateTrunk5DownList);
        int trunk5Flow = trunk5UpFlow + trunk5DownFlow;
        result.setVhc15(trunk5Flow);
        // 6型货车
        List<RoadFlowCalculateVO> calculateTrunk6UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC16.getField());
        int trunk6UpFlow = this.calculateRoadFlow(calculateTrunk6UpList);
        List<RoadFlowCalculateVO> calculateTrunk6DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC16.getField());
        int trunk6DownFlow = this.calculateRoadFlow(calculateTrunk6DownList);
        int trunk6Flow = trunk6UpFlow + trunk6DownFlow;
        result.setVhc16(trunk6Flow);
        return ResultUtil.success(result);
    }

    @Override
    public Result<List<GantryHourFlowWideVO>> getCrossOverviewCarReport(CrossOverviewStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 起止门架不能为空
        String startEndPlace = request.getStartEndPlace();
        if (StringUtils.isEmpty(startEndPlace)) {
            return ResultUtil.fail("起止门架不能为空!");
        }
        // -之前的门架
        String firstPlace = startEndPlace.split(ProjectConstant.MINUS)[0];
        // -之后的门架
        String lastPlace = startEndPlace.split(ProjectConstant.MINUS)[1];
        List<String> places = new ArrayList<>();
        places.add(firstPlace);
        places.add(lastPlace);
        // 查询两个收费站之间所属的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .in(AMjHxl::getStartPlace, places)
                .in(AMjHxl::getEndPlace, places)
        );
        // 查询数据
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        List<GantryHourFlowWideVO> flowList = gantryHourFlowWideMapper.getFlow(request);
        // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
        String timeType = request.getTimeType();
        // 根据开始时间、结束时间、时间类型生成时间点列表
        List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
        // 返回列表
        List<GantryHourFlowWideVO> result = new ArrayList<>();
        // 遍历时间点列表并获取对应的数据
        for (int i = 0; i < timePointList.size() - 1; i++) {
            GantryHourFlowWideVO report = new GantryHourFlowWideVO();
            // 当前时间点
            String timePoint = timePointList.get(i);
            Date timePointDate = DateUtil.parse(timePoint);
            // 下一个时间点
            String nextTimePoint = timePointList.get(i + 1);
            Date nextTimePointDate = DateUtil.parse(nextTimePoint);
            // 时间点
            String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
            report.setTimePoint(timePointDisplay);
            int vhc1 = 0;
            int vhc2 = 0;
            int vhc3 = 0;
            int vhc4 = 0;
            int vhc11 = 0;
            int vhc12 = 0;
            int vhc13 = 0;
            int vhc14 = 0;
            int vhc15 = 0;
            int vhc16 = 0;
            int vhc21 = 0;
            int vhc22 = 0;
            int vhc23 = 0;
            int vhc24 = 0;
            int vhc25 = 0;
            int vhc26 = 0;
            // 这个时间段内的客车流量数据(大于等于timePoint,小于nextTimePoint)
            if (CollectionUtil.isNotEmpty(flowList)) {
                List<GantryHourFlowWideVO> carFlowList = flowList.stream()
                        .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                        .collect(Collectors.toList());
                // 客车1总流量
                vhc1 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum();
                // 客车2总流量
                vhc2 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum();
                // 客车3总流量
                vhc3 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum();
                // 客车4总流量
                vhc4 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum();
                // 货车1总流量
                vhc11 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum();
                // 货车2总流量
                vhc12 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum();
                // 货车3总流量
                vhc13 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum();
                // 货车4总流量
                vhc14 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum();
                // 货车5总流量
                vhc15 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum();
                // 货车6总流量
                vhc16 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum();
                // 专项车1总流量
                vhc21 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum();
                // 专项车2总流量
                vhc22 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum();
                // 专项车3总流量
                vhc23 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum();
                // 专项车4总流量
                vhc24 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum();
                // 专项车5总流量
                vhc25 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum();
                // 专项车6总流量
                vhc26 = carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum();
            }
            report.setVhc1(vhc1);
            report.setVhc2(vhc2);
            report.setVhc3(vhc3);
            report.setVhc4(vhc4);
            report.setVhc11(vhc11);
            report.setVhc12(vhc12);
            report.setVhc13(vhc13);
            report.setVhc14(vhc14);
            report.setVhc15(vhc15);
            report.setVhc16(vhc16);
            report.setVhc21(vhc21);
            report.setVhc22(vhc22);
            report.setVhc23(vhc23);
            report.setVhc24(vhc24);
            report.setVhc25(vhc25);
            report.setVhc26(vhc26);
            result.add(report);
        }
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(result);
        }
        CarTypeEnum.setCarTypeListFLow(carTypeChoose, result);
        return ResultUtil.success(result);
    }

    @Override
    public Result<List<CrossOverviewStatisticReport>> getRoadCarReport(RoadStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 路段不能为空
        String road = request.getRoad();
        if (StringUtils.isEmpty(road)) {
            return ResultUtil.fail("路段不能为空!");
        }
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 门架
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 查询初始数据
        List<GantryHourFlowWideVO> flowList = gantryHourFlowWideMapper.getRoadFlowDetail(request);
        // 上行列表
        List<GantryHourFlowWideVO> upList = flowList.stream()
                .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                .collect(Collectors.toList());
        // 下行列表
        List<GantryHourFlowWideVO> downList = flowList.stream()
                .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                .collect(Collectors.toList());
        // 返回列表
        List<CrossOverviewStatisticReport> reports = new ArrayList<>();

        // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
        String timeType = request.getTimeType();
        // 根据开始时间、结束时间、时间类型生成时间点列表
        List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
        // 遍历时间点列表并获取对应的数据
        for (int i = 0; i < timePointList.size() - 1; i++) {
            // 客车流量
            int busFlow = 0;
            // 货车流量
            int truckFlow = 0;
            // 客车1流量
            int bus1Flow = 0;
            // 客车2流量
            int bus2Flow = 0;
            // 客车3流量
            int bus3Flow = 0;
            // 客车4流量
            int bus4Flow = 0;
            // 货车1流量
            int truck1Flow = 0;
            // 货车2流量
            int truck2Flow = 0;
            // 货车3流量
            int truck3Flow = 0;
            // 货车4流量
            int truck4Flow = 0;
            // 货车5流量
            int truck5Flow = 0;
            // 货车6流量
            int truck6Flow = 0;
            CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
            // 当前时间点
            String timePoint = timePointList.get(i);
            Date timePointDate = DateUtil.parse(timePoint);
            // 下一个时间点
            String nextTimePoint = timePointList.get(i + 1);
            Date nextTimePointDate = DateUtil.parse(nextTimePoint);
            // 时间点
            String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
            report.setTimePoint(timePointDisplay);
            // 这个时间段内的上行流量数据(大于等于timePoint,小于nextTimePoint)
            if (CollectionUtil.isNotEmpty(upList)) {
                List<GantryHourFlowWideVO> upItemList = upList.stream()
                        .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                        .collect(Collectors.toList());
                // 对上行流量数据进行处理(相同门架的数据对应的字段进行累加,保证一个门架只有一条数据)
                List<GantryHourFlowWideVO> upSumList = new ArrayList<>();
                for (GantryHourFlowWideVO item : upItemList) {
                    if (CollectionUtil.isEmpty(upSumList)) {
                        upSumList.add(item);
                    } else {
                        // 判断是否存在相同门架的数据
                        GantryHourFlowWideVO gantryHourFlowWideVO = upSumList.stream()
                                .filter(sumItem -> item.getGrantryId().equals(sumItem.getGrantryId()))
                                .findFirst()
                                .orElse(null);
                        if (gantryHourFlowWideVO != null) {
                            // 如果已经存在该门架数据,则对对应字段进行累加
                            gantryHourFlowWideVO.setVhc1(gantryHourFlowWideVO.getVhc1() + item.getVhc1());
                            gantryHourFlowWideVO.setVhc2(gantryHourFlowWideVO.getVhc2() + item.getVhc2());
                            gantryHourFlowWideVO.setVhc3(gantryHourFlowWideVO.getVhc3() + item.getVhc3());
                            gantryHourFlowWideVO.setVhc4(gantryHourFlowWideVO.getVhc4() + item.getVhc4());
                            gantryHourFlowWideVO.setVhc11(gantryHourFlowWideVO.getVhc11() + item.getVhc11());
                            gantryHourFlowWideVO.setVhc12(gantryHourFlowWideVO.getVhc12() + item.getVhc12());
                            gantryHourFlowWideVO.setVhc13(gantryHourFlowWideVO.getVhc13() + item.getVhc13());
                            gantryHourFlowWideVO.setVhc14(gantryHourFlowWideVO.getVhc14() + item.getVhc14());
                            gantryHourFlowWideVO.setVhc15(gantryHourFlowWideVO.getVhc15() + item.getVhc15());
                            gantryHourFlowWideVO.setVhc16(gantryHourFlowWideVO.getVhc16() + item.getVhc16());
                        } else {
                            // 如果不存在该门架,则直接添加数据
                            upSumList.add(item);
                        }
                    }
                }
                // 上行总流量
                List<RoadFlowCalculateVO> calculateUpTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, ProjectConstant.TOTAL_FLOW);
                int upFlow = this.calculateRoadFlow(calculateUpTotalList);
                report.setUpFlow(upFlow);
                // 客车上行流量
                List<RoadFlowCalculateVO> calculateUpBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, ProjectConstant.BUS_FLOW);
                busFlow += this.calculateRoadFlow(calculateUpBusList);
                // 货车上行流量
                List<RoadFlowCalculateVO> calculateUpTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, ProjectConstant.TRUCK_FLOW);
                truckFlow += this.calculateRoadFlow(calculateUpTruckList);
                // 客车1上行流量
                List<RoadFlowCalculateVO> calculateUpVhc1List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC1.getField());
                bus1Flow += this.calculateRoadFlow(calculateUpVhc1List);
                // 客车2上行流量
                List<RoadFlowCalculateVO> calculateUpVhc2List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC2.getField());
                bus2Flow += this.calculateRoadFlow(calculateUpVhc2List);
                // 客车3上行流量
                List<RoadFlowCalculateVO> calculateUpVhc3List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC3.getField());
                bus3Flow += this.calculateRoadFlow(calculateUpVhc3List);
                // 客车4上行流量
                List<RoadFlowCalculateVO> calculateUpVhc4List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC4.getField());
                bus4Flow += this.calculateRoadFlow(calculateUpVhc4List);
                // 货车1上行流量
                List<RoadFlowCalculateVO> calculateUpVhc11List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC11.getField());
                truck1Flow += this.calculateRoadFlow(calculateUpVhc11List);
                // 货车2上行流量
                List<RoadFlowCalculateVO> calculateUpVhc12List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC12.getField());
                truck2Flow += this.calculateRoadFlow(calculateUpVhc12List);
                // 货车3上行流量
                List<RoadFlowCalculateVO> calculateUpVhc13List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC13.getField());
                truck3Flow += this.calculateRoadFlow(calculateUpVhc13List);
                // 货车4上行流量
                List<RoadFlowCalculateVO> calculateUpVhc14List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC14.getField());
                truck4Flow += this.calculateRoadFlow(calculateUpVhc14List);
                // 货车5上行流量
                List<RoadFlowCalculateVO> calculateUpVhc15List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC15.getField());
                truck5Flow += this.calculateRoadFlow(calculateUpVhc15List);
                // 货车6上行流量
                List<RoadFlowCalculateVO> calculateUpVhc16List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upSumList, CarTypeEnum.VHC16.getField());
                truck6Flow += this.calculateRoadFlow(calculateUpVhc16List);
            }
            // 这个时间段内的下行流量数据(大于等于timePoint,小于nextTimePoint)
            if (CollectionUtil.isNotEmpty(downList)) {
                List<GantryHourFlowWideVO> downItemList = downList.stream()
                        .filter(item -> item.getTime() != null &&  item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                        .collect(Collectors.toList());
                // 对上行流量数据进行处理(相同门架的数据对应的字段进行累加,保证一个门架只有一条数据)
                List<GantryHourFlowWideVO> downSumList = new ArrayList<>();
                for (GantryHourFlowWideVO item : downItemList) {
                    if (CollectionUtil.isEmpty(downSumList)) {
                        downSumList.add(item);
                    } else {
                        // 判断是否存在相同门架的数据
                        GantryHourFlowWideVO gantryHourFlowWideVO = downSumList.stream()
                                .filter(sumItem -> item.getGrantryId().equals(sumItem.getGrantryId()))
                                .findFirst()
                                .orElse(null);
                        if (gantryHourFlowWideVO != null) {
                            // 如果已经存在该门架数据,则对对应字段进行累加
                            gantryHourFlowWideVO.setVhc1(gantryHourFlowWideVO.getVhc1() + item.getVhc1());
                            gantryHourFlowWideVO.setVhc2(gantryHourFlowWideVO.getVhc2() + item.getVhc2());
                            gantryHourFlowWideVO.setVhc3(gantryHourFlowWideVO.getVhc3() + item.getVhc3());
                            gantryHourFlowWideVO.setVhc4(gantryHourFlowWideVO.getVhc4() + item.getVhc4());
                            gantryHourFlowWideVO.setVhc11(gantryHourFlowWideVO.getVhc11() + item.getVhc11());
                            gantryHourFlowWideVO.setVhc12(gantryHourFlowWideVO.getVhc12() + item.getVhc12());
                            gantryHourFlowWideVO.setVhc13(gantryHourFlowWideVO.getVhc13() + item.getVhc13());
                            gantryHourFlowWideVO.setVhc14(gantryHourFlowWideVO.getVhc14() + item.getVhc14());
                            gantryHourFlowWideVO.setVhc15(gantryHourFlowWideVO.getVhc15() + item.getVhc15());
                            gantryHourFlowWideVO.setVhc16(gantryHourFlowWideVO.getVhc16() + item.getVhc16());
                        } else {
                            // 如果不存在该门架,则直接添加数据
                            downSumList.add(item);
                        }
                    }
                }
                // 下行总流量
                List<RoadFlowCalculateVO> calculateDownTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, ProjectConstant.TOTAL_FLOW);
                int downFlow = this.calculateRoadFlow(calculateDownTotalList);
                report.setDownFlow(downFlow);
                // 客车下行流量
                List<RoadFlowCalculateVO> calculateDownBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, ProjectConstant.BUS_FLOW);
                busFlow += this.calculateRoadFlow(calculateDownBusList);
                // 货车下行流量
                List<RoadFlowCalculateVO> calculateDownTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, ProjectConstant.TRUCK_FLOW);
                truckFlow += this.calculateRoadFlow(calculateDownTruckList);
                // 客车1下行流量
                List<RoadFlowCalculateVO> calculateDownVhc1List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC1.getField());
                bus1Flow += this.calculateRoadFlow(calculateDownVhc1List);
                // 客车2下行流量
                List<RoadFlowCalculateVO> calculateDownVhc2List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC2.getField());
                bus2Flow += this.calculateRoadFlow(calculateDownVhc2List);
                // 客车3下行流量
                List<RoadFlowCalculateVO> calculateDownVhc3List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC3.getField());
                bus3Flow += this.calculateRoadFlow(calculateDownVhc3List);
                // 客车4下行流量
                List<RoadFlowCalculateVO> calculateDownVhc4List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC4.getField());
                bus4Flow += this.calculateRoadFlow(calculateDownVhc4List);
                // 货车1下行流量
                List<RoadFlowCalculateVO> calculateDownVhc11List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC11.getField());
                truck1Flow += this.calculateRoadFlow(calculateDownVhc11List);
                // 货车2下行流量
                List<RoadFlowCalculateVO> calculateDownVhc12List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC12.getField());
                truck2Flow += this.calculateRoadFlow(calculateDownVhc12List);
                // 货车3下行流量
                List<RoadFlowCalculateVO> calculateDownVhc13List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC13.getField());
                truck3Flow += this.calculateRoadFlow(calculateDownVhc13List);
                // 货车4下行流量
                List<RoadFlowCalculateVO> calculateDownVhc14List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC14.getField());
                truck4Flow += this.calculateRoadFlow(calculateDownVhc14List);
                // 货车5下行流量
                List<RoadFlowCalculateVO> calculateDownVhc15List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC15.getField());
                truck5Flow += this.calculateRoadFlow(calculateDownVhc15List);
                // 货车6下行流量
                List<RoadFlowCalculateVO> calculateDownVhc16List = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downSumList, CarTypeEnum.VHC16.getField());
                truck6Flow += this.calculateRoadFlow(calculateDownVhc16List);
            }
            // 总流量
            report.setTotalFlow(busFlow + truckFlow);
            // 客车流量
            report.setBusFlow(busFlow);
            // 货车流量
            report.setTruckFlow(truckFlow);
            // 客车1流量
            report.setVhc1(bus1Flow);
            // 客车2流量
            report.setVhc2(bus2Flow);
            // 客车3流量
            report.setVhc3(bus3Flow);
            // 客车4流量
            report.setVhc4(bus4Flow);
            // 货车1流量
            report.setVhc11(truck1Flow);
            // 货车2流量
            report.setVhc12(truck2Flow);
            // 货车3流量
            report.setVhc13(truck3Flow);
            // 货车4流量
            report.setVhc14(truck4Flow);
            // 货车5流量
            report.setVhc15(truck5Flow);
            // 货车6流量
            report.setVhc16(truck6Flow);
            reports.add(report);
        }
        return ResultUtil.success(reports);
    }

    @Override
    public Result<List<CrossOverviewStatisticReport>> getGantryFlowReport(CommonRequest request) {
        // 时间类型定死按日
        request.setTimeType(ProjectConstant.DAY);
        GantryHourFlowWideVO maxTimeRecord = gantryHourFlowWideMapper.getMaxTimeRecord();
        // 获取这条记录时间的日期部分
        Date maxDate = DateUtil.parse(DateUtil.format(maxTimeRecord.getTime(), "yyyy-MM-dd"));
        // 开始时间是最后一次更新数据日期的0点0分0秒
        request.setStartTime(DateUtil.format(maxDate, "yyyy-MM-dd") + " 00:00:00");
        // 结束时间是最后一次更新数据日期的23点59分59秒
        request.setEndTime(DateUtil.format(maxDate, "yyyy-MM-dd") + " 23:59:59");
        // TODO-后期删除目前数据有问题直接给3月11日
        request.setStartTime("2025-03-11 00:00:00");
        request.setEndTime("2025-03-11 23:59:59");
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 按请求查询数据
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getTrafficRankReportInGantry(request);
        // 返回列表
        List<CrossOverviewStatisticReport> reports = new ArrayList<>();
        records.forEach(record -> {
            // 方向
            String direction = record.getDirection();
            // 判断reports中是否已经存在该起止门架
            if (this.isExitInGantryFlow(reports, record)) {
                CrossOverviewStatisticReport report = this.getExitReportItemInGantryFlow(reports, record);
                // 客车累计流量 = 原客车车累计流量 + 1234型客车流量
                report.setBusFlow(report.getBusFlow() + record.getVhc1() + record.getVhc2() + record.getVhc3() + record.getVhc4());
                // 货车累计流量 = 原货车车累计流量 + 123456型货车流量
                report.setTruckFlow(report.getTruckFlow() + record.getVhc11() + record.getVhc12() + record.getVhc13() + record.getVhc14() + record.getVhc15() + record.getVhc16());
                // 总流量 = 货车累计流量 + 客车累计流量
                report.setTotalFlow(report.getBusFlow() + report.getTruckFlow());
                int allCarFlow = record.getVhc1() + record.getVhc2() + record.getVhc3() + record.getVhc4()
                        + record.getVhc11() + record.getVhc12() + record.getVhc13() + record.getVhc14() + record.getVhc15() + record.getVhc16();
                if (ProjectConstant.UP.equals(direction)) {
                    int oldUpFlow = report.getUpFlow() != null ? report.getUpFlow() : 0;
                    report.setUpFlow(oldUpFlow + allCarFlow);
                } else if (ProjectConstant.DOWN.equals(direction)) {
                    int oldDownFlow = report.getDownFlow() != null ? report.getDownFlow() : 0;
                    report.setDownFlow(oldDownFlow + allCarFlow);
                }
                // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                report.setVhc1(record.getVhc1() + report.getVhc1());
                report.setVhc2(record.getVhc2() + report.getVhc2());
                report.setVhc3(record.getVhc3() + report.getVhc3());
                report.setVhc4(record.getVhc4() + report.getVhc4());
                report.setVhc11(record.getVhc11() + report.getVhc11());
                report.setVhc12(record.getVhc12() + report.getVhc12());
                report.setVhc13(record.getVhc13() + report.getVhc13());
                report.setVhc14(record.getVhc14() + report.getVhc14());
                report.setVhc15(record.getVhc15() + report.getVhc15());
                report.setVhc16(record.getVhc16() + report.getVhc16());
                report.setVhc21(record.getVhc21() + report.getVhc21());
                report.setVhc22(record.getVhc22() + report.getVhc22());
                report.setVhc23(record.getVhc23() + report.getVhc23());
                report.setVhc24(record.getVhc24() + report.getVhc24());
                report.setVhc25(record.getVhc25() + report.getVhc25());
                report.setVhc26(record.getVhc26() + report.getVhc26());
                if (ProjectConstant.UP.equals(direction)) {
                    int oldUpVhc1 = report.getUpVhc1() != null ? report.getUpVhc1() : 0;
                    report.setUpVhc1(oldUpVhc1 + record.getVhc1());
                    int oldUpVhc2 = report.getUpVhc2() != null ? report.getUpVhc2() : 0;
                    report.setUpVhc2(oldUpVhc2 + record.getVhc2());
                    int oldUpVhc3 = report.getUpVhc3() != null ? report.getUpVhc3() : 0;
                    report.setUpVhc3(oldUpVhc3 + record.getVhc3());
                    int oldUpVhc4 = report.getUpVhc4() != null ? report.getUpVhc4() : 0;
                    report.setUpVhc4(oldUpVhc4 + record.getVhc4());
                    int oldUpVhc11 = report.getUpVhc11() != null ? report.getUpVhc11() : 0;
                    report.setUpVhc11(oldUpVhc11 + record.getVhc11());
                    int oldUpVhc12 = report.getUpVhc12() != null ? report.getUpVhc12() : 0;
                    report.setUpVhc12(oldUpVhc12 + record.getVhc12());
                    int oldUpVhc13 = report.getUpVhc13() != null ? report.getUpVhc13() : 0;
                    report.setUpVhc13(oldUpVhc13 + record.getVhc13());
                    int oldUpVhc14 = report.getUpVhc14() != null ? report.getUpVhc14() : 0;
                    report.setUpVhc14(oldUpVhc14 + record.getVhc14());
                    int oldUpVhc15 = report.getUpVhc15() != null ? report.getUpVhc15() : 0;
                    report.setUpVhc15(oldUpVhc15 + record.getVhc15());
                    int oldUpVhc16 = report.getUpVhc16() != null ? report.getUpVhc16() : 0;
                    report.setUpVhc16(oldUpVhc16 + record.getVhc16());
                    int oldUpVhc21 = report.getUpVhc21() != null ? report.getUpVhc21() : 0;
                    report.setUpVhc21(oldUpVhc21 + record.getVhc21());
                    int oldUpVhc22 = report.getUpVhc22() != null ? report.getUpVhc22() : 0;
                    report.setUpVhc22(oldUpVhc22 + record.getVhc22());
                    int oldUpVhc23 = report.getUpVhc23() != null ? report.getUpVhc23() : 0;
                    report.setUpVhc23(oldUpVhc23 + record.getVhc23());
                    int oldUpVhc24 = report.getUpVhc24() != null ? report.getUpVhc24() : 0;
                    report.setUpVhc24(oldUpVhc24 + record.getVhc24());
                    int oldUpVhc25 = report.getUpVhc25() != null ? report.getUpVhc25() : 0;
                    report.setUpVhc25(oldUpVhc25 + record.getVhc25());
                    int oldUpVhc26 = report.getUpVhc26() != null ? report.getUpVhc26() : 0;
                    report.setUpVhc26(oldUpVhc26 + record.getVhc26());
                } else if (ProjectConstant.DOWN.equals(direction)) {
                    int oldDownVhc1 = report.getDownVhc1() != null ? report.getDownVhc1() : 0;
                    report.setDownVhc1(oldDownVhc1 + record.getVhc1());
                    int oldDownVhc2 = report.getDownVhc2() != null ? report.getDownVhc2() : 0;
                    report.setDownVhc2(oldDownVhc2 + record.getVhc2());
                    int oldDownVhc3 = report.getDownVhc3() != null ? report.getDownVhc3() : 0;
                    report.setDownVhc3(oldDownVhc3 + record.getVhc3());
                    int oldDownVhc4 = report.getDownVhc4() != null ? report.getDownVhc4() : 0;
                    report.setDownVhc4(oldDownVhc4 + record.getVhc4());
                    int oldDownVhc11 = report.getDownVhc11() != null ? report.getDownVhc11() : 0;
                    report.setDownVhc11(oldDownVhc11 + record.getVhc11());
                    int oldDownVhc12 = report.getDownVhc12() != null ? report.getDownVhc12() : 0;
                    report.setDownVhc12(oldDownVhc12 + record.getVhc12());
                    int oldDownVhc13 = report.getDownVhc13() != null ? report.getDownVhc13() : 0;
                    report.setDownVhc13(oldDownVhc13 + record.getVhc13());
                    int oldDownVhc14 = report.getDownVhc14() != null ? report.getDownVhc14() : 0;
                    report.setDownVhc14(oldDownVhc14 + record.getVhc14());
                    int oldDownVhc15 = report.getDownVhc15() != null ? report.getDownVhc15() : 0;
                    report.setDownVhc15(oldDownVhc15 + record.getVhc15());
                    int oldDownVhc16 = report.getDownVhc16() != null ? report.getDownVhc16() : 0;
                    report.setDownVhc16(oldDownVhc16 + record.getVhc16());
                    int oldDownVhc21 = report.getDownVhc21() != null ? report.getDownVhc21() : 0;
                    report.setDownVhc21(oldDownVhc21 + record.getVhc21());
                    int oldDownVhc22 = report.getDownVhc22() != null ? report.getDownVhc22() : 0;
                    report.setDownVhc22(oldDownVhc22 + record.getVhc22());
                    int oldDownVhc23 = report.getDownVhc23() != null ? report.getDownVhc23() : 0;
                    report.setDownVhc23(oldDownVhc23 + record.getVhc23());
                    int oldDownVhc24 = report.getDownVhc24() != null ? report.getDownVhc24() : 0;
                    report.setDownVhc24(oldDownVhc24 + record.getVhc24());
                    int oldDownVhc25 = report.getDownVhc25() != null ? report.getDownVhc25() : 0;
                    report.setDownVhc25(oldDownVhc25 + record.getVhc25());
                    int oldDownVhc26 = report.getDownVhc26() != null ? report.getDownVhc26() : 0;
                    report.setDownVhc26(oldDownVhc26 + record.getVhc26());
                }
            } else {
                this.createReportItemInGantryFlow(reports, record);
            }
        });
        // 对reports按照总流量降序进行排序
        reports.sort(Comparator.comparingInt(CrossOverviewStatisticReport::getTotalFlow).reversed());
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(reports);
        }
        CarTypeEnum.calculateAndSetObjectFlowUpDownListFlow(carTypeChoose, reports);
        return ResultUtil.success(reports);
    }

    @Override
    public List<String> getGantryIdsByStartEndStationId(String startStationId, String endStationId) {
        // 获取所有收费站信息
        List<StationRoadAreaInfo> stationList = stationRoadAreaInfoService.list();
        // stationId-StationRoadAreaInfo对象映射
        Map<String, StationRoadAreaInfo> stationMap = stationList.stream()
                .collect(Collectors.toMap(StationRoadAreaInfo::getStationId, v -> v));
        // 判断两个门架是否在同一条路上
        if (!this.isInSameRoad(startStationId, endStationId)) {
            // 如果不在同一条路上,则返回空集合
            return new ArrayList<>();
        }
        // 开始门架对象
        StationRoadAreaInfo stationRoadAreaInfoStart = stationMap.get(startStationId);
        // 开始桩号数值
        Integer startPileNum = stationRoadAreaInfoStart.getPileNumValue();
        // 结束门架对象
        StationRoadAreaInfo stationRoadAreaInfoEnd = stationMap.get(endStationId);
        // 结束桩号数值
        Integer endPileNum = stationRoadAreaInfoEnd.getPileNumValue();
        // 所在路段
        String roadCode = stationRoadAreaInfoStart.getRoadCode();
        // 较大的桩号
        Integer pileNumValueMax = Math.max(startPileNum, endPileNum);
        // 较小的桩号
        Integer pileNumValueMin = Math.min(startPileNum, endPileNum);
        // 查询门架列表
        List<GantryRoadAreaInfo> gantryRoadAreaInfoList = gantryRoadAreaInfoService.list(new LambdaQueryWrapper<GantryRoadAreaInfo>()
                // 在该路段下
                .eq(GantryRoadAreaInfo::getRoadCode, roadCode)
                // 桩号数值大于开始桩号数值
                .ge(GantryRoadAreaInfo::getPileNumValue, pileNumValueMin)
                // 桩号数值小于结束桩号数值
                .le(GantryRoadAreaInfo::getPileNumValue, pileNumValueMax)
        );
        return gantryRoadAreaInfoList.stream()
                .map(GantryRoadAreaInfo::getGantryId)
                .collect(Collectors.toList());
    }

    @Override
    public Result<List<CrossOverviewStatisticReport>> getRoadStatisticReportInLastEightDay(RoadStatisticRequest request) {
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 统计类型不能为空
        String statisticType = request.getStatisticType();
        if (StringUtils.isEmpty(statisticType)) {
            return ResultUtil.fail("统计类型不能为空!");
        }
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 门架
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 查询该路段拥有的门架id列表
        List<AMjHxl> list = aMjHxlService.list();
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 返回列表
        List<CrossOverviewStatisticReport> result = new ArrayList<>();
        if (ProjectConstant.DIRECTION.equals(statisticType)) {
            // 上行列表
            List<AMjHxl> upGantryList = list.stream().filter(aMjHxl -> aMjHxl.getFx().equals(ProjectConstant.UP)).collect(Collectors.toList());
            // 下行列表
            List<AMjHxl> downGantryList = list.stream().filter(aMjHxl -> aMjHxl.getFx().equals(ProjectConstant.DOWN)).collect(Collectors.toList());
            // 查询上行数据
            CrossOverviewStatisticRequest upRequest = BeanUtil.copyProperties(request, CrossOverviewStatisticRequest.class);
            upRequest.setGantryIds(upGantryList.stream().map(AMjHxl::getMjid).collect(Collectors.toList()));
            List<GantryHourFlowWideVO> upList = gantryHourFlowWideMapper.getFlow(upRequest);
            // 查询下行数据
            CrossOverviewStatisticRequest downRequest = BeanUtil.copyProperties(request, CrossOverviewStatisticRequest.class);
            downRequest.setGantryIds(downGantryList.stream().map(AMjHxl::getMjid).collect(Collectors.toList()));
            List<GantryHourFlowWideVO> downList = gantryHourFlowWideMapper.getFlow(downRequest);
            // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
            String timeType = request.getTimeType();
            // 根据开始时间、结束时间、时间类型生成时间点列表
            List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
            // 遍历时间点列表并获取对应的数据
            for (int i = 0; i < timePointList.size() - 1; i++) {
                CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
                // 当前时间点
                String timePoint = timePointList.get(i);
                Date timePointDate = DateUtil.parse(timePoint);
                // 下一个时间点
                String nextTimePoint = timePointList.get(i + 1);
                Date nextTimePointDate = DateUtil.parse(nextTimePoint);
                // 时间点
                String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
                report.setTimePoint(timePointDisplay);
                // 这个时间段内的上行流量数据(大于等于timePoint,小于nextTimePoint)
                int upTotalFlow = 0;
                if (CollectionUtil.isNotEmpty(upList)) {
                    List<GantryHourFlowWideVO> upItemList = upList.stream()
                            .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                            .collect(Collectors.toList());
                    // 上行总流量
                    upTotalFlow = upItemList.stream()
                            .mapToInt(item ->
                                    item.getVhc1() + item.getVhc2() + item.getVhc3() + item.getVhc4() +
                                    item.getVhc11() + item.getVhc12() + item.getVhc13() + item.getVhc14() + item.getVhc15() + item.getVhc16())
                            .sum();
                    // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                    report.setUpVhc1(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum());
                    report.setUpVhc2(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum());
                    report.setUpVhc3(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum());
                    report.setUpVhc4(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum());
                    report.setUpVhc11(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum());
                    report.setUpVhc12(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum());
                    report.setUpVhc13(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum());
                    report.setUpVhc14(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum());
                    report.setUpVhc15(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum());
                    report.setUpVhc16(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum());
                    report.setUpVhc21(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum());
                    report.setUpVhc22(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum());
                    report.setUpVhc23(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum());
                    report.setUpVhc24(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum());
                    report.setUpVhc25(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum());
                    report.setUpVhc26(upItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum());
                }
                // 这个时间段内的下行流量数据(大于等于timePoint,小于nextTimePoint)
                int downTotalFlow = 0;
                if (CollectionUtil.isNotEmpty(downList)) {
                    List<GantryHourFlowWideVO> downItemList = downList.stream()
                            .filter(item -> item.getTime() != null &&  item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                            .collect(Collectors.toList());
                    // 下行总流量
                    downTotalFlow = downItemList.stream()
                            .mapToInt(item ->
                                    item.getVhc1() + item.getVhc2() + item.getVhc3() + item.getVhc4() +
                                    item.getVhc11() + item.getVhc12() + item.getVhc13() + item.getVhc14() + item.getVhc15() + item.getVhc16())
                            .sum();
                    // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                    report.setDownVhc1(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum());
                    report.setDownVhc2(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum());
                    report.setDownVhc3(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum());
                    report.setDownVhc4(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum());
                    report.setDownVhc11(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum());
                    report.setDownVhc12(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum());
                    report.setDownVhc13(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum());
                    report.setDownVhc14(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum());
                    report.setDownVhc15(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum());
                    report.setDownVhc16(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum());
                    report.setDownVhc21(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum());
                    report.setDownVhc22(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum());
                    report.setDownVhc23(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum());
                    report.setDownVhc24(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum());
                    report.setDownVhc25(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum());
                    report.setDownVhc26(downItemList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum());
                }
                // 总流量
                Integer totalFlow = upTotalFlow + downTotalFlow;
                report.setUpFlow(upTotalFlow);
                report.setDownFlow(downTotalFlow);
                report.setTotalFlow(totalFlow);
                result.add(report);
            }
        } else if (ProjectConstant.CAR_TYPE.equals(statisticType)) {
            // 查询数据
            request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
            List<GantryHourFlowWideVO> flowList = gantryHourFlowWideMapper.getFlow(request);
            // 根据时间类型区分,填写所属时间点并在这个时间点内做累加
            String timeType = request.getTimeType();
            // 根据开始时间、结束时间、时间类型生成时间点列表
            List<String> timePointList = DateTimeUtil.generateTimeList(request.getStartTime(), request.getEndTime(), timeType);
            // 遍历时间点列表并获取对应的数据
            for (int i = 0; i < timePointList.size() - 1; i++) {
                CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
                // 当前时间点
                String timePoint = timePointList.get(i);
                Date timePointDate = DateUtil.parse(timePoint);
                // 下一个时间点
                String nextTimePoint = timePointList.get(i + 1);
                Date nextTimePointDate = DateUtil.parse(nextTimePoint);
                // 时间点
                String timePointDisplay = DateTimeUtil.getTimePoint(timePoint, timeType);
                report.setTimePoint(timePointDisplay);
                int busFlow = 0;
                int truckFlow = 0;
                int containerFlow = 0;
                // 这个时间段内的客车流量数据(大于等于timePoint,小于nextTimePoint)
                if (CollectionUtil.isNotEmpty(flowList)) {
                    List<GantryHourFlowWideVO> carFlowList = flowList.stream()
                            .filter(item -> item.getTime() != null && item.getTime().compareTo(timePointDate) >= 0 && item.getTime().compareTo(nextTimePointDate) < 0)
                            .collect(Collectors.toList());
                    // 客车总流量
                    busFlow = carFlowList.stream()
                            .mapToInt(item -> item.getVhc1() + item.getVhc2() + item.getVhc3() + item.getVhc4()).sum();
                    // 货车总流量
                    truckFlow = carFlowList.stream()
                            .mapToInt(item -> item.getVhc11() + item.getVhc12() + item.getVhc13() + item.getVhc14() + item.getVhc15() + item.getVhc16()).sum();
                    // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
                    report.setVhc1(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc1).sum());
                    report.setVhc2(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc2).sum());
                    report.setVhc3(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc3).sum());
                    report.setVhc4(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc4).sum());
                    report.setVhc11(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc11).sum());
                    report.setVhc12(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc12).sum());
                    report.setVhc13(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc13).sum());
                    report.setVhc14(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc14).sum());
                    report.setVhc15(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc15).sum());
                    report.setVhc16(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc16).sum());
                    report.setVhc21(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc21).sum());
                    report.setVhc22(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc22).sum());
                    report.setVhc23(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc23).sum());
                    report.setVhc24(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc24).sum());
                    report.setVhc25(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc25).sum());
                    report.setVhc26(carFlowList.stream().mapToInt(GantryHourFlowWideVO::getVhc26).sum());
                }
                report.setBusFlow(busFlow);
                report.setTruckFlow(truckFlow);
                report.setContainerFlow(containerFlow);
                int totalFlow = busFlow + truckFlow + containerFlow;
                report.setTotalFlow(totalFlow);
                result.add(report);
            }
        }
        // 车型选择
        String carTypeChoose = request.getCarTypeChoose();
        // 如果对车型没有选择,直接返回
        if (StringUtils.isEmpty(carTypeChoose)) {
            return ResultUtil.success(result);
        }
        CarTypeEnum.calculateAndSetObjectFlowUpDownListFlow(carTypeChoose, result);
        return ResultUtil.success(result);
    }

    @Override
    public Result<List<RoadRankReport>> getStationFlow(CommonRequest request) {
        // 时间类型定死按日
        request.setTimeType(ProjectConstant.DAY);
        GantryHourFlowWideVO maxTimeRecord = gantryHourFlowWideMapper.getMaxTimeRecord();
        // 获取这条记录时间的日期部分
        Date maxDate = DateUtil.parse(DateUtil.format(maxTimeRecord.getTime(), "yyyy-MM-dd"));
        // 开始时间是最后一次更新数据日期的0点0分0秒
        request.setStartTime(DateUtil.format(maxDate, "yyyy-MM-dd") + " 00:00:00");
        // 结束时间是最后一次更新数据日期的23点59分59秒
        request.setEndTime(DateUtil.format(maxDate, "yyyy-MM-dd") + " 23:59:59");
        // TODO-后期删除目前数据有问题直接给3月11日
        request.setStartTime("2025-03-11 00:00:00");
        request.setEndTime("2025-03-11 23:59:59");
        String isValid = QueryUtil.isValid(request);
        // 判断请求是否合法
        if (!ProjectConstant.TRUE.equals(isValid)) {
            return ResultUtil.fail(isValid);
        }
        // 道路默认直接传入
        String road = request.getRoad();
        // 开始收费站id
        String startStationId = request.getStartStationId();
        // 结束收费站id
        String endStationId = request.getEndStationId();
        // 开始-结束收费站所包含的门架id列表
        List<String> startEndGantryIncludeIds = new ArrayList<>();
        // 较大的桩号
        Integer pileNumValueMax = null;
        // 较小的桩号
        Integer pileNumValueMin = null;
        // 自选模式的条件
        if (StringUtils.isNotEmpty(startStationId) && StringUtils.isNotEmpty(endStationId)) {
            boolean flag = this.isInSameRoad(startStationId, endStationId);
            // 如果不在同一个道路上,抛出异常
            if (!flag) {
                return ResultUtil.fail("所选择的开始和结束收费站必须位于同一道路上");
            }
            // 根据开始和结束收费站id获取所包含的门架id
            startEndGantryIncludeIds = this.getGantryIdsByStartEndStationId(startStationId, endStationId);
            // 如果没有包含任何门架直接返回空
            if (CollectionUtil.isEmpty(startEndGantryIncludeIds)) {
                return ResultUtil.success(new ArrayList<>());
            }
            // 开始收费站实体类
            StationRoadAreaInfo startStationInfo = stationRoadAreaInfoService.getOne(new LambdaQueryWrapper<StationRoadAreaInfo>()
                    .eq(StationRoadAreaInfo::getStationId, startStationId)
            );
            // 开始收费站所在桩号
            Integer pileNumStart = startStationInfo.getPileNumValue();
            // 结束收费站实体类
            StationRoadAreaInfo endStationInfo = stationRoadAreaInfoService.getOne(new LambdaQueryWrapper<StationRoadAreaInfo>()
                    .eq(StationRoadAreaInfo::getStationId, endStationId)
            );
            // 结束收费站所在桩号
            Integer pileNumEnd = endStationInfo.getPileNumValue();
            pileNumValueMax = Math.max(pileNumStart, pileNumEnd);
            pileNumValueMin = Math.min(pileNumStart, pileNumEnd);
            // 自选模式的道路就是所选收费站的所在道路
            road = stationRoadAreaInfoService.getRoadCodeByStationId(startStationId);
        }
        request.setStartEndGantryIncludeIds(startEndGantryIncludeIds);
        // 获取所有收费站信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list(new LambdaQueryWrapper<GantryRoadAreaInfo>()
                .eq(StringUtils.isNotEmpty(road), GantryRoadAreaInfo::getRoadCode, road)
                // 大于等于较小的桩号
                .ge(pileNumValueMin != null, GantryRoadAreaInfo::getPileNumValue, pileNumValueMin)
                // 小于等于较大的桩号
                .le(pileNumValueMax != null, GantryRoadAreaInfo::getPileNumValue, pileNumValueMax)
        );
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 获取所有收费站信息
        List<StationRoadAreaInfo> stationList = stationRoadAreaInfoService.list(new LambdaQueryWrapper<StationRoadAreaInfo>()
            .eq(StringUtils.isNotEmpty(road), StationRoadAreaInfo::getRoadCode, road)
                // 大于等于较小的桩号
                .ge(pileNumValueMin != null, StationRoadAreaInfo::getPileNumValue, pileNumValueMin)
                // 小于等于较大的桩号
                .le(pileNumValueMax != null, StationRoadAreaInfo::getPileNumValue, pileNumValueMax)
        );
        // 路段id-List<StationRoadAreaInfo>映射,并且List中的pileNumValue字段按照从小到大排序
        Map<String, List<StationRoadAreaInfo>> roadStationMap = stationList.stream()
                .collect(Collectors.groupingBy(StationRoadAreaInfo::getRoadCode,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> list.stream()
                                        .sorted(Comparator.comparing(StationRoadAreaInfo::getPileNumValue)
                                                .thenComparing(StationRoadAreaInfo::getStationId))
                                        .collect(Collectors.toList())
                        )));
        // 构建一个所在路段_开始收费站id_结束收费站id-门架id列表集合
        Map<String, List<String>> stationGantryIdsMap = new HashMap<>();
        roadStationMap.forEach((roadCode, stationRoadAreaInfos) -> {
            for (int i = 0; i < stationRoadAreaInfos.size() - 1; i++) {
                StationRoadAreaInfo startStation = stationRoadAreaInfos.get(i);
                StationRoadAreaInfo endStation = stationRoadAreaInfos.get(i + 1);
                String startId = startStation.getStationId();
                String endId = endStation.getStationId();
                String key = roadCode + ProjectConstant.UNDERLINE + startId + ProjectConstant.UNDERLINE + endId;
                List<String> gantryIds = this.getGantryIdsByStartEndStationId(startId, endId);
                stationGantryIdsMap.put(key, gantryIds);
            }
        });
        // 按请求查询数据(查询精确到门架)
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
        List<RoadRankReport> reports = new ArrayList<>();
        if (records.isEmpty()) {
            return ResultUtil.success(reports);
        }
        // 查询同一路段的收费站经纬度信息
        List<TobjTollStationInfo> tollStationInfos = tobjTollStationInfoService.list();
        // 构建stationId-TobjTollStationInfo映射
        Map<String, TobjTollStationInfo> tollStationInfoMap = tollStationInfos.stream()
                .collect(Collectors.toMap(TobjTollStationInfo::getStationId, Function.identity()));
        // 查询收费站桩号信息
        List<StationRoadAreaInfo> stationRoadAreaInfos = stationRoadAreaInfoService.list();
        // 构建stationId-StationRoadAreaInfo映射
        Map<String, StationRoadAreaInfo> stationRoadAreaInfoMap = stationRoadAreaInfos.stream()
                .collect(Collectors.toMap(StationRoadAreaInfo::getStationId, Function.identity()));
        stationGantryIdsMap.forEach((key, gantryIdList) -> {
            RoadRankReport report = new RoadRankReport();
            // 道路
            String roadCode = key.split(ProjectConstant.UNDERLINE)[0];
            report.setRoad(roadCode);
            // 开始收费站id
            String startId = key.split(ProjectConstant.UNDERLINE)[1];
            report.setStationStartId(startId);
            // 开始收费站实体类
            TobjTollStationInfo startStationInfo = tollStationInfoMap.get(startId);
            if (startStationInfo != null) {
                report.setStationStartLng(startStationInfo.getLng());
                report.setStationStartLat(startStationInfo.getLat());
            }
            // 开始收费站桩号实体类
            StationRoadAreaInfo startStation = stationRoadAreaInfoMap.get(startId);
            if (startStation != null) {
                report.setPileNumStart(startStation.getPileNum());
                report.setPileNumStartValue(startStation.getPileNumValue());
            }
            // 结束收费站id
            String endId = key.split(ProjectConstant.UNDERLINE)[2];
            report.setStationEndId(endId);
            // 结束收费站实体类
            TobjTollStationInfo endStationInfo = tollStationInfoMap.get(endId);
            if (endStationInfo != null) {
                report.setStationEndLng(endStationInfo.getLng());
                report.setStationEndLat(endStationInfo.getLat());
            }
            // 结束收费站桩号实体类
            StationRoadAreaInfo endStation = stationRoadAreaInfoMap.get(endId);
            if (endStation != null) {
                report.setPileNumEnd(endStation.getPileNum());
                report.setPileNumEndValue(endStation.getPileNumValue());
            }
            // 当前开始结束收费站对应的数据列表
            List<GantryHourFlowWideVO> currentRecords = records.stream()
                    .filter(record -> gantryIdList.contains(record.getGrantryId()))
                    .collect(Collectors.toList());
            // 计算总流量
            List<RoadFlowCalculateVO> calculateCurrentList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, currentRecords, ProjectConstant.TOTAL_FLOW);
            // 上行列表
            List<RoadFlowCalculateVO> upList = calculateCurrentList.stream()
                    .filter(record -> ProjectConstant.UP.equals(record.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downList = calculateCurrentList.stream()
                    .filter(record -> ProjectConstant.DOWN.equals(record.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int roadTotalFlowUp = this.calculateRoadFlow(upList);
            // 计算收费站之间的下行流量
            int roadTotalFlowDown = this.calculateRoadFlow(downList);
            // 总流量 = 上行流量 + 下行流量
            int totalFlow = roadTotalFlowUp + roadTotalFlowDown;
            report.setTotalFlow(totalFlow);
            reports.add(report);
        });
        // 对开始收费站的桩号进行从小到大排序
        reports.sort(Comparator.comparingInt(RoadRankReport::getPileNumStartValue));
        return ResultUtil.success(reports);
    }

    @Override
    public Result<FestivalTrafficReport> getSingleFestivalReport(FestivalTrafficRequest request) {
        // 返回实体
        FestivalTrafficReport report = new FestivalTrafficReport();
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        Integer holidayType = request.getHolidayType();
        if (holidayType == null) {
            return ResultUtil.fail("单个节假日节假日类型必传");
        }
        // 根据年份节假日类型查询开始和结束时间
        HolidayRequest holidayRequest = new HolidayRequest();
        holidayRequest.setType(holidayType);
        holidayRequest.setYear(year);
        // 今年该节假日的时间列表
        List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
        if (CollectionUtil.isNotEmpty(holidayDateList)) {
            // 开始时间是第一项
            String startTime = holidayDateList.get(0) + " 00:00:00";
            request.setStartTime(startTime);
            // 结束时间是最后一项
            String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
            request.setEndTime(endTime);
            // 获取所有信息
            List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
            // 获取道路编码-门架id映射
            Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
            // 获取区域-门架id映射
            Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
            // 门架id-GantryRoadAreaInfo映射
            Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
            // 道路
            String road = request.getRoad();
            if (StringUtils.isNotEmpty(road)) {
                List<String> roadGantryIds = roadMap.get(road);
                request.setRoadGantryIds(roadGantryIds);
            }
            // 区域
            String area = request.getArea();
            if (StringUtils.isNotEmpty(area)) {
                List<String> areaGantryIds = areaMap.get(area);
                request.setAreaGantryIds(areaGantryIds);
            }
            // 按请求查询数据(查询精确到门架)
            List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
            if (CollectionUtil.isNotEmpty(records)) {
                // 分路段计算总流量
                List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TOTAL_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                // 总流量
                int thisYearTotalFlow = 0;
                // 算流量要一条一条路算
                for (String roadName : roadTotalFlowMap.keySet()) {
                    // 对应列表
                    List<RoadFlowCalculateVO> list = roadTotalFlowMap.get(roadName);
                    // 这一年该节日的上行列表
                    List<RoadFlowCalculateVO> upFlowList = list.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 这一年该节日的下行列表
                    List<RoadFlowCalculateVO> downFlowList = list.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int totalFlowUp = this.calculateRoadFlow(upFlowList);
                    // 计算收费站之间的下行流量
                    int totalFlowDown = this.calculateRoadFlow(downFlowList);
                    // 总流量 = 上行流量 + 下行流量
                    int totalFlow = totalFlowUp + totalFlowDown;
                    thisYearTotalFlow += totalFlow;
                }
                // 分路段计算客车总流量
                List<RoadFlowCalculateVO> calculateBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.BUS_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadBusFlowMap = calculateBusList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                // 客车流量
                int thisYearBusFlow = 0;
                // 算流量要一条一条路算
                for (String roadName : roadBusFlowMap.keySet()) {
                    // 对应列表
                    List<RoadFlowCalculateVO> list = roadBusFlowMap.get(roadName);
                    // 这一年该节日的客车上行列表
                    List<RoadFlowCalculateVO> busUpFlowList = list.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 这一年该节日的客车下行列表
                    List<RoadFlowCalculateVO> busDownFlowList = list.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int busFlowUp = this.calculateRoadFlow(busUpFlowList);
                    // 计算收费站之间的下行流量
                    int busFlowDown = this.calculateRoadFlow(busDownFlowList);
                    int busFlow = busFlowUp + busFlowDown;
                    thisYearBusFlow += busFlow;
                }
                // 分路段计算货车总流量
                List<RoadFlowCalculateVO> calculateTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TRUCK_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadTruckFlowMap = calculateTruckList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                // 货车流量
                int thisYearTruckFlow = 0;
                for (String roadName : roadTruckFlowMap.keySet()) {
                    // 对应列表
                    List<RoadFlowCalculateVO> list = roadTruckFlowMap.get(roadName);
                    // 这一年该节日的货车上行列表
                    List<RoadFlowCalculateVO> truckUpFlowList = list.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 这一年该节日的货车下行列表
                    List<RoadFlowCalculateVO> truckDownFlowList = list.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int truckFlowUp = this.calculateRoadFlow(truckUpFlowList);
                    // 计算收费站之间的下行流量
                    int truckFlowDown = this.calculateRoadFlow(truckDownFlowList);
                    int truckFlow = truckFlowUp + truckFlowDown;
                    thisYearTruckFlow += truckFlow;
                }
                // 集装箱车流量
                int thisYearContainerFlow = 0;
                report.setThisYearTotalFlow(thisYearTotalFlow);
                report.setThisYearBusFlow(thisYearBusFlow);
                report.setThisYearTruckFlow(thisYearTruckFlow);
                report.setThisYearContainerFlow(thisYearContainerFlow);
            }
        }
        return ResultUtil.success(report);
    }

    @Override
    public Result<List<FestivalTrafficReport>> getMultipleFestivalReport(FestivalTrafficRequest request) {
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        // 计算免通或非免通的数据集合通行类型必传
        Boolean freePass = request.getFreePass();
        if (freePass == null) {
            return ResultUtil.fail("计算免通或非免通的数据集合通行类型必传");
        }
        List<FestivalTrafficReport> reportList = new ArrayList<>();
        // 获取对应的节假日列表
        List<HolidayVO> holidayList = HolidayEnum.getHolidayListByFreePass(freePass);
        List<Integer> holidayTypeList = holidayList.stream()
                .map(HolidayVO::getType)
                .collect(Collectors.toList());
        // 遍历节假日类型列表,每个节假日分开计算,最后再求和
        for (Integer holidayType : holidayTypeList) {
            FestivalTrafficReport report = new FestivalTrafficReport();
            // 节假日名称
            String festivalName = HolidayEnum.getNameByType(holidayType);
            report.setFestivalName(festivalName);
            // 总流量
            int thisYearTotalFlow = 0;
            // 根据年份节假日类型查询开始和结束时间
            HolidayRequest holidayRequest = new HolidayRequest();
            holidayRequest.setType(holidayType);
            holidayRequest.setYear(year);
            // 今年该节假日的时间列表
            List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
            if (CollectionUtil.isNotEmpty(holidayDateList)) {
                // 开始时间是第一项
                String startTime = holidayDateList.get(0) + " 00:00:00";
                request.setStartTime(startTime);
                // 结束时间是最后一项
                String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
                request.setEndTime(endTime);
                // 获取所有信息
                List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
                // 获取道路编码-门架id映射
                Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                        .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
                // 获取区域-门架id映射
                Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                        .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
                // 门架id-GantryRoadAreaInfo映射
                Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                        .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
                // 道路
                String road = request.getRoad();
                if (StringUtils.isNotEmpty(road)) {
                    List<String> roadGantryIds = roadMap.get(road);
                    request.setRoadGantryIds(roadGantryIds);
                }
                // 区域
                String area = request.getArea();
                if (StringUtils.isNotEmpty(area)) {
                    List<String> areaGantryIds = areaMap.get(area);
                    request.setAreaGantryIds(areaGantryIds);
                }
                // 按请求查询数据(查询精确到门架)
                List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
                if (CollectionUtil.isNotEmpty(records)) {
                    // 分路段计算总流量
                    List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TOTAL_FLOW);
                    // 路段编号-List<RoadFlowCalculateVO>映射
                    Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                            .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                    // 算流量要一条一条路算
                    for (String roadName : roadTotalFlowMap.keySet()) {
                        // 对应列表
                        List<RoadFlowCalculateVO> list = roadTotalFlowMap.get(roadName);
                        // 这一年该节日的上行列表
                        List<RoadFlowCalculateVO> upFlowList = list.stream()
                                .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                                .collect(Collectors.toList());
                        // 这一年该节日的下行列表
                        List<RoadFlowCalculateVO> downFlowList = list.stream()
                                .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                                .collect(Collectors.toList());
                        // 计算收费站之间的上行流量
                        int totalFlowUp = this.calculateRoadFlow(upFlowList);
                        // 计算收费站之间的下行流量
                        int totalFlowDown = this.calculateRoadFlow(downFlowList);
                        // 总流量 = 上行流量 + 下行流量
                        int totalFlow = totalFlowUp + totalFlowDown;
                        thisYearTotalFlow += totalFlow;
                    }
                }
            }
            report.setThisYearTotalFlow(thisYearTotalFlow);
            reportList.add(report);
        }
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<List<FestivalTrafficRankReport>> getFestivalRoadRankReport(FestivalTrafficRequest request) {
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        // 分析类型
        String analysisType = request.getAnalysisType();
        if (StringUtils.isEmpty(analysisType)) {
            return ResultUtil.fail("分析类型必传");
        }
        List<FestivalTrafficRankReport> reportList = new ArrayList<>();
        if (ProjectConstant.SINGLE.equals(analysisType)) {
            // 单个节假日分析
            Integer holidayType = request.getHolidayType();
            if (holidayType == null) {
                return ResultUtil.fail("单个节假日节假日类型必传");
            }
            reportList = this.getFestivalRoadRankReport(request, year, holidayType);
        } else if (ProjectConstant.MULTIPLE.equals(analysisType)) {
            // 多个节假日分析
            Boolean freePass = request.getFreePass();
            if (freePass == null) {
                return ResultUtil.fail("多个节假日是否免通行必传");
            }
            List<HolidayVO> holidayVOList = HolidayEnum.getHolidayListByFreePass(freePass);
            // 节假日类型列表
            List<Integer> holidayTypeList = holidayVOList.stream()
                    .map(HolidayVO::getType)
                    .collect(Collectors.toList());
            reportList = new ArrayList<>();
            for (int i = 0; i < holidayTypeList.size(); i++) {
                Integer holidayType = holidayTypeList.get(i);
                // 一个一个依次去计算
                List<FestivalTrafficRankReport> itemList = this.getFestivalRoadRankReport(request, year, holidayType);
                // 第一项直接放入，后面的项做累加
                if (i == 0) {
                    reportList.addAll(itemList);
                } else {
                    for (FestivalTrafficRankReport report : reportList) {
                        for (FestivalTrafficRankReport item : itemList) {
                            // 路段对应,对数据做累加
                            if (report.getRoadName().equals(item.getRoadName())) {
                                report.setTotalFlow(report.getTotalFlow() + item.getTotalFlow());
                                report.setBusFlow(report.getBusFlow() + item.getBusFlow());
                                report.setTruckFlow(report.getTruckFlow() + item.getTruckFlow());
                                report.setContainerFlow(report.getContainerFlow() + item.getContainerFlow());
                                break;
                            }
                        }
                    }
                }
            }
        }
        // 对总流量进行降序排序
        if (CollectionUtil.isNotEmpty(reportList)) {
            reportList.sort(Comparator.comparingInt(FestivalTrafficRankReport::getTotalFlow).reversed());
        }
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<List<FestivalSingleFlowReport>> getFestivalSingleFlowReport(FestivalTrafficRequest request) {
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        // 单个节假日分析
        Integer holidayType = request.getHolidayType();
        if (holidayType == null) {
            return ResultUtil.fail("单个节假日节假日类型必传");
        }
        // 返回
        List<FestivalSingleFlowReport> reportList = this.getFestivalSingleDailyFlow(request, holidayType, year, ProjectConstant.SINGLE);
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<List<FestivalMultipleFlowReport>> getFestivalMultipleFlowReport(FestivalTrafficRequest request) {
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        // 多个节假日分析
        Boolean freePass = request.getFreePass();
        if (freePass == null) {
            return ResultUtil.fail("多个节假日是否免通行必传");
        }
        List<HolidayVO> holidayVOList = HolidayEnum.getHolidayListByFreePass(freePass);
        // 节假日类型列表
        List<Integer> holidayTypeList = holidayVOList.stream()
                .map(HolidayVO::getType)
                .collect(Collectors.toList());
        // 返回
        List<FestivalMultipleFlowReport> reportList = new ArrayList<>();
        // 遍历节假日类型列表
        for (Integer holidayType : holidayTypeList) {
            FestivalMultipleFlowReport report = new FestivalMultipleFlowReport();
            // 根据节假日类型获取节假日名称
            String festivalName = HolidayEnum.getNameByType(holidayType);
            report.setFestivalName(festivalName);
            // 获取该节假日单日流量集合
            List<FestivalSingleFlowReport> itemList = this.getFestivalSingleDailyFlow(request, holidayType, year, ProjectConstant.MULTIPLE);
            report.setFestivalSingleFlowReportList(itemList);
            reportList.add(report);
        }
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<List<FestivalMultipleFlowReport>> getFestivalSingleTrendReport(FestivalTrafficRequest request) {
        // 返回
        List<FestivalMultipleFlowReport> reportList = new ArrayList<>();
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        // 单个节假日分析
        Integer holidayType = request.getHolidayType();
        if (holidayType == null) {
            return ResultUtil.fail("单个节假日节假日类型必传");
        }
        // 根据年份节假日类型查询开始和结束时间
        HolidayRequest holidayRequest = new HolidayRequest();
        holidayRequest.setType(holidayType);
        holidayRequest.setYear(year);
        // 今年该节假日的时间列表
        List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
        // 开始时间
        String startTime = holidayDateList.get(0) + " 00:00:00";
        request.setStartTime(startTime);
        // 结束时间
        String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
        request.setEndTime(endTime);
        // 道路
        String road = request.getRoad();
        // 查询这个路段所包含的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .eq(StringUtils.isNotEmpty(road), AMjHxl::getRoad, road)
        );
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 设置门架id
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 按请求查询数据(查询精确到门架)
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlowDetail(request);
        // 遍历日期列表
        for (String holidayDate : holidayDateList) {
            FestivalMultipleFlowReport report = new FestivalMultipleFlowReport();
            // 日期
            report.setDate(holidayDate);
            // 开始时间
            String holidayDateStart = holidayDate + " 00:00:00";
            // 结束时间
            String holidayDateEnd = holidayDate + " 23:59:59";
            List<FestivalSingleFlowReport> itemList = new ArrayList<>();
            // 根据开始时间、结束时间、时间类型生成时间点列表
            List<String> timePointList = DateTimeUtil.generateTimeList(holidayDateStart, holidayDateEnd, ProjectConstant.HOUR);
            for (int i = 0; i < timePointList.size() - 1; i++) {
                FestivalSingleFlowReport itemReport = new FestivalSingleFlowReport();
                // 表示第几个小时
                itemReport.setTimePoint(String.valueOf(i));
                // 当前时间点
                String timePoint = timePointList.get(i);
                Date timePointDate = DateUtil.parse(timePoint);
                // 下一个时间点
                String nextTimePoint = timePointList.get(i + 1);
                Date nextTimePointDate = DateUtil.parse(nextTimePoint);
                // 过滤得到介于这两个时间点内的数据
                List<GantryHourFlowWideVO> itemRecords = records.stream()
                        .filter(item ->
                                item.getTime() != null &&
                                item.getTime().compareTo(timePointDate) >= 0 &&
                                item.getTime().compareTo(nextTimePointDate) < 0)
                        .collect(Collectors.toList());
                // 将同一个门架下的流量字段合并
                List<GantryHourFlowWideVO> processRecords = this.processGantryRecords(itemRecords);
                // 分路段计算总流量
                List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processRecords, ProjectConstant.TOTAL_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                int totalFlow = 0;
                // 算流量要一条一条路算
                for (String roadName : roadTotalFlowMap.keySet()) {
                    // 对应列表
                    List<RoadFlowCalculateVO> calculateList = roadTotalFlowMap.get(roadName);
                    // 上行列表
                    List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 下行列表
                    List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int totalFlowUp = this.calculateRoadFlow(upFlowList);
                    // 计算收费站之间的下行流量
                    int totalFlowDown = this.calculateRoadFlow(downFlowList);
                    // 总流量 = 上行流量 + 下行流量
                    int roadTotalFlow = totalFlowUp + totalFlowDown;
                    totalFlow += roadTotalFlow;
                }
                itemReport.setTotalFlow(totalFlow);
                itemList.add(itemReport);
            }
            report.setFestivalSingleFlowReportList(itemList);
            reportList.add(report);
        }
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<GantryHourFlowWideVO> getFestivalSingleVehicle(FestivalTrafficRequest request) {
        // 年份
        Integer year = request.getYear();
        if (year == null) {
            return ResultUtil.fail("年份必传");
        }
        // 单个节假日分析
        Integer holidayType = request.getHolidayType();
        if (holidayType == null) {
            return ResultUtil.fail("单个节假日节假日类型必传");
        }
        // 根据年份节假日类型查询开始和结束时间
        HolidayRequest holidayRequest = new HolidayRequest();
        holidayRequest.setType(holidayType);
        holidayRequest.setYear(year);
        // 今年该节假日的时间列表
        List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
        // 开始时间
        String startTime = holidayDateList.get(0) + " 00:00:00";
        request.setStartTime(startTime);
        // 结束时间
        String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
        request.setEndTime(endTime);
        // 道路
        String road = request.getRoad();
        // 查询这个路段所包含的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .eq(StringUtils.isNotEmpty(road), AMjHxl::getRoad, road)
        );
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 道路
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 设置门架id
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 按请求查询数据(查询精确到门架)
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
        GantryHourFlowWideVO result = new GantryHourFlowWideVO();
        if (records.isEmpty()) {
            return ResultUtil.success(result);
        }
        // 上行数据
        List<GantryHourFlowWideVO> upRecords = records.stream()
                .filter(record -> ProjectConstant.UP.equals(record.getDirection()))
                .collect(Collectors.toList());
        // 下行数据
        List<GantryHourFlowWideVO> downRecords = records.stream()
                .filter(record -> ProjectConstant.DOWN.equals(record.getDirection()))
                .collect(Collectors.toList());
        // 1型客车
        List<RoadFlowCalculateVO> calculateBus1UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC1.getField());
        int bus1UpFlow = this.calculateRoadFlow(calculateBus1UpList);
        List<RoadFlowCalculateVO> calculateBus1DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC1.getField());
        int bus1DownFlow = this.calculateRoadFlow(calculateBus1DownList);
        int bus1Flow = bus1UpFlow + bus1DownFlow;
        result.setVhc1(bus1Flow);
        // 2型客车
        List<RoadFlowCalculateVO> calculateBus2UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC2.getField());
        int bus2UpFlow = this.calculateRoadFlow(calculateBus2UpList);
        List<RoadFlowCalculateVO> calculateBus2DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC2.getField());
        int bus2DownFlow = this.calculateRoadFlow(calculateBus2DownList);
        int bus2Flow = bus2UpFlow + bus2DownFlow;
        result.setVhc2(bus2Flow);
        // 3型客车
        List<RoadFlowCalculateVO> calculateBus3UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC3.getField());
        int bus3UpFlow = this.calculateRoadFlow(calculateBus3UpList);
        List<RoadFlowCalculateVO> calculateBus3DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC3.getField());
        int bus3DownFlow = this.calculateRoadFlow(calculateBus3DownList);
        int bus3Flow = bus3UpFlow + bus3DownFlow;
        result.setVhc3(bus3Flow);
        // 4型客车
        List<RoadFlowCalculateVO> calculateBus4UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC4.getField());
        int bus4UpFlow = this.calculateRoadFlow(calculateBus4UpList);
        List<RoadFlowCalculateVO> calculateBus4DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC4.getField());
        int bus4DownFlow = this.calculateRoadFlow(calculateBus4DownList);
        int bus4Flow = bus4UpFlow + bus4DownFlow;
        result.setVhc4(bus4Flow);
        // 1型货车
        List<RoadFlowCalculateVO> calculateTrunk1UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC11.getField());
        int trunk1UpFlow = this.calculateRoadFlow(calculateTrunk1UpList);
        List<RoadFlowCalculateVO> calculateTrunk1DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC11.getField());
        int trunk1DownFlow = this.calculateRoadFlow(calculateTrunk1DownList);
        int trunk1Flow = trunk1UpFlow + trunk1DownFlow;
        result.setVhc11(trunk1Flow);
        // 2型货车
        List<RoadFlowCalculateVO> calculateTrunk2UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC12.getField());
        int trunk2UpFlow = this.calculateRoadFlow(calculateTrunk2UpList);
        List<RoadFlowCalculateVO> calculateTrunk2DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC12.getField());
        int trunk2DownFlow = this.calculateRoadFlow(calculateTrunk2DownList);
        int trunk2Flow = trunk2UpFlow + trunk2DownFlow;
        result.setVhc12(trunk2Flow);
        // 3型货车
        List<RoadFlowCalculateVO> calculateTrunk3UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC13.getField());
        int trunk3UpFlow = this.calculateRoadFlow(calculateTrunk3UpList);
        List<RoadFlowCalculateVO> calculateTrunk3DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC13.getField());
        int trunk3DownFlow = this.calculateRoadFlow(calculateTrunk3DownList);
        int trunk3Flow = trunk3UpFlow + trunk3DownFlow;
        result.setVhc13(trunk3Flow);
        // 4型货车
        List<RoadFlowCalculateVO> calculateTrunk4UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC14.getField());
        int trunk4UpFlow = this.calculateRoadFlow(calculateTrunk4UpList);
        List<RoadFlowCalculateVO> calculateTrunk4DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC14.getField());
        int trunk4DownFlow = this.calculateRoadFlow(calculateTrunk4DownList);
        int trunk4Flow = trunk4UpFlow + trunk4DownFlow;
        result.setVhc14(trunk4Flow);
        // 5型货车
        List<RoadFlowCalculateVO> calculateTrunk5UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC15.getField());
        int trunk5UpFlow = this.calculateRoadFlow(calculateTrunk5UpList);
        List<RoadFlowCalculateVO> calculateTrunk5DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC15.getField());
        int trunk5DownFlow = this.calculateRoadFlow(calculateTrunk5DownList);
        int trunk5Flow = trunk5UpFlow + trunk5DownFlow;
        result.setVhc15(trunk5Flow);
        // 6型货车
        List<RoadFlowCalculateVO> calculateTrunk6UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC16.getField());
        int trunk6UpFlow = this.calculateRoadFlow(calculateTrunk6UpList);
        List<RoadFlowCalculateVO> calculateTrunk6DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC16.getField());
        int trunk6DownFlow = this.calculateRoadFlow(calculateTrunk6DownList);
        int trunk6Flow = trunk6UpFlow + trunk6DownFlow;
        result.setVhc16(trunk6Flow);
        return ResultUtil.success(result);
    }

    @Override
    public Result<List<FestivalMultipleFlowReport>> getFestivalHistoricalTrend(FestivalTrafficRequest request) {
        // 多个节假日分析
        Boolean freePass = request.getFreePass();
        if (freePass == null) {
            return ResultUtil.fail("多个节假日是否免通行必传");
        }
        List<HolidayVO> holidayVOList = HolidayEnum.getHolidayListByFreePass(freePass);
        // 节假日类型列表
        List<Integer> holidayTypeList = holidayVOList.stream()
                .map(HolidayVO::getType)
                .collect(Collectors.toList());
        // 历史统计年份列表
        List<Integer> yearList = new ArrayList<>();
        // 今年的年份
        int thisYear = DateUtil.thisYear();
        // 从两年前到今年
        for (int i = thisYear - 2; i <= thisYear; i++) {
            yearList.add(i);
        }
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 返回
        List<FestivalMultipleFlowReport> reportList = new ArrayList<>();
        // 遍历节假日列表
        for (Integer holidayType : holidayTypeList) {
            FestivalMultipleFlowReport report = new FestivalMultipleFlowReport();
            // 每个节假日都有个列表用于存放对应的时间节点和流量
            List<FestivalSingleFlowReport> flowReports = new ArrayList<>();
            // 根据节假日类型获取节假日名称
            String holidayName = HolidayEnum.getNameByType(holidayType);
            report.setFestivalName(holidayName);
            // 遍历年份列表一年一年来计算
            for (Integer year : yearList) {
                FestivalSingleFlowReport flowReport = new FestivalSingleFlowReport();
                flowReport.setTimePoint(String.valueOf(year));
                // 根据年份节假日类型查询开始和结束时间
                HolidayRequest holidayRequest = new HolidayRequest();
                holidayRequest.setType(holidayType);
                holidayRequest.setYear(year);
                // 指定年该节假日的时间列表
                List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
                // 总流量
                int thisYearHolidayTotalFlow = 0;
                if (CollectionUtil.isNotEmpty(holidayDateList)) {
                    // 开始时间是第一项
                    String startTime = holidayDateList.get(0) + " 00:00:00";
                    request.setStartTime(startTime);
                    // 结束时间是最后一项
                    String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
                    request.setEndTime(endTime);
                    // 道路
                    String road = request.getRoad();
                    if (StringUtils.isNotEmpty(road)) {
                        List<String> roadGantryIds = roadMap.get(road);
                        request.setRoadGantryIds(roadGantryIds);
                    }
                    // 区域
                    String area = request.getArea();
                    if (StringUtils.isNotEmpty(area)) {
                        List<String> areaGantryIds = areaMap.get(area);
                        request.setAreaGantryIds(areaGantryIds);
                    }
                    // 按请求查询数据(查询精确到门架)
                    List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
                    if (CollectionUtil.isNotEmpty(records)) {
                        // 分路段计算总流量
                        List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TOTAL_FLOW);
                        // 路段编号-List<RoadFlowCalculateVO>映射
                        Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                        // 算流量要一条一条路算
                        for (String roadName : roadTotalFlowMap.keySet()) {
                            // 对应列表
                            List<RoadFlowCalculateVO> list = roadTotalFlowMap.get(roadName);
                            // 这一年该节日的上行列表
                            List<RoadFlowCalculateVO> upFlowList = list.stream()
                                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                                    .collect(Collectors.toList());
                            // 这一年该节日的下行列表
                            List<RoadFlowCalculateVO> downFlowList = list.stream()
                                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                                    .collect(Collectors.toList());
                            // 计算收费站之间的上行流量
                            int totalFlowUp = this.calculateRoadFlow(upFlowList);
                            // 计算收费站之间的下行流量
                            int totalFlowDown = this.calculateRoadFlow(downFlowList);
                            // 总流量 = 上行流量 + 下行流量
                            int totalFlow = totalFlowUp + totalFlowDown;
                            thisYearHolidayTotalFlow += totalFlow;
                        }
                    }
                }
                flowReport.setTotalFlow(thisYearHolidayTotalFlow);
                flowReports.add(flowReport);
            }
            report.setFestivalSingleFlowReportList(flowReports);
            reportList.add(report);
        }
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<MorningEveningOverviewReport> getMorningEveningOverviewReport(FestivalTrafficRequest request) {
        // 日期必传
        String date = request.getDate();
        if (StringUtils.isEmpty(date)) {
            return ResultUtil.fail("早晚流量日期必传");
        }
        MorningEveningOverviewReport report = new MorningEveningOverviewReport();
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 开始时间是这一天的0点0分0秒
        String startTime = date + " 00:00:00";
        request.setStartTime(startTime);
        // 结束时间是这一天的23点59分59秒
        String endTime = date + " 23:59:59";
        request.setEndTime(endTime);
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 这一天的早高峰开始时间
        String morningStartTime = date + " " + ProjectConstant.EARLY_PEAK_START_TIME;
        Date morningStartDateTime = DateUtil.parse(morningStartTime);
        // 这一天的早高峰结束时间
        String morningEndTime = date + " " + ProjectConstant.EARLY_PEAK_END_TIME;
        Date morningEndDateTime = DateUtil.parse(morningEndTime);
        // 这一天的晚高峰开始时间
        String lateStartTime = date + " " + ProjectConstant.LATE_PEAK_START_TIME;
        Date lateStartDateTime = DateUtil.parse(lateStartTime);
        // 这一天的晚高峰结束时间
        String lateEndTime = date + " " + ProjectConstant.LATE_PEAK_END_TIME;
        Date lateEndDateTime = DateUtil.parse(lateEndTime);
        // 查询这一天范围内的数据
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlowDetail(request);
        // 早高峰数据
        List<GantryHourFlowWideVO> morningRecords = records.stream()
                .filter(item ->
                        item.getTime() != null &&
                        item.getTime().compareTo(morningStartDateTime) >= 0 &&
                        item.getTime().compareTo(morningEndDateTime) < 0)
                .collect(Collectors.toList());
        // 将同一个门架下的流量字段合并
        List<GantryHourFlowWideVO> processMorningRecords = this.processGantryRecords(morningRecords);
        /**
         * 早高峰总流量计算
         */
        // 分路段计算总流量
        List<RoadFlowCalculateVO> morningCalculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processMorningRecords, ProjectConstant.TOTAL_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> morningRoadTotalFlowMap = morningCalculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int earlyTotalFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : morningRoadTotalFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = morningRoadTotalFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int totalFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int totalFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadTotalFlow = totalFlowUp + totalFlowDown;
            earlyTotalFlow += roadTotalFlow;
        }
        report.setEarlyTotalFlow(earlyTotalFlow);
        /**
         * 早高峰客车流量计算
         */
        List<RoadFlowCalculateVO> morningCalculateBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processMorningRecords, ProjectConstant.BUS_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> morningRoadBusFlowMap = morningCalculateBusList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int earlyBusFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : morningRoadBusFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = morningRoadBusFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int busFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int busFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadBusFlow = busFlowUp + busFlowDown;
            earlyBusFlow += roadBusFlow;
        }
        report.setBusEarlyFlow(earlyBusFlow);
        /**
         * 早高峰货车流量计算
         */
        List<RoadFlowCalculateVO> morningCalculateTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processMorningRecords, ProjectConstant.TRUCK_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> morningRoadTruckFlowMap = morningCalculateTruckList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int earlyTruckFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : morningRoadTruckFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = morningRoadTruckFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int trunkFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int trunkFlowDown = this.calculateRoadFlow(downFlowList);
            int roadTrunkFlow = trunkFlowUp + trunkFlowDown;
            earlyTruckFlow += roadTrunkFlow;
        }
        report.setTruckEarlyFlow(earlyTruckFlow);
        report.setContainerEarlyFlow(0);

        // 晚高峰数据
        List<GantryHourFlowWideVO> eveningRecords = records.stream()
                .filter(item ->
                        item.getTime() != null &&
                        item.getTime().compareTo(lateStartDateTime) >= 0 &&
                        item.getTime().compareTo(lateEndDateTime) < 0)
                .collect(Collectors.toList());
        // 将同一个门架下的流量字段合并
        List<GantryHourFlowWideVO> processEveningRecords = this.processGantryRecords(eveningRecords);
        /**
         * 晚高峰总流量计算
         */
        // 分路段计算总流量
        List<RoadFlowCalculateVO> eveningCalculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processEveningRecords, ProjectConstant.TOTAL_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> eveningRoadTotalFlowMap = eveningCalculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int eveningTotalFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : eveningRoadTotalFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = eveningRoadTotalFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int totalFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int totalFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadTotalFlow = totalFlowUp + totalFlowDown;
            eveningTotalFlow += roadTotalFlow;
        }
        report.setLateTotalFlow(eveningTotalFlow);
        /**
         * 晚高峰客车流量计算
         */
        List<RoadFlowCalculateVO> eveningCalculateBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processEveningRecords, ProjectConstant.BUS_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> eveningRoadBusFlowMap = eveningCalculateBusList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int eveningBusFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : eveningRoadBusFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = eveningRoadBusFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int busFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int busFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadBusFlow = busFlowUp + busFlowDown;
            eveningBusFlow += roadBusFlow;
        }
        report.setBusLateFlow(eveningBusFlow);
        /**
         * 早高峰货车流量计算
         */
        List<RoadFlowCalculateVO> eveningCalculateTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processEveningRecords, ProjectConstant.TRUCK_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> eveningRoadTruckFlowMap = eveningCalculateTruckList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int eveningTruckFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : eveningRoadTruckFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = eveningRoadTruckFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int trunkFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int trunkFlowDown = this.calculateRoadFlow(downFlowList);
            int roadTrunkFlow = trunkFlowUp + trunkFlowDown;
            eveningTruckFlow += roadTrunkFlow;
        }
        report.setTruckLateFlow(eveningTruckFlow);
        report.setContainerLateFlow(0);
        return ResultUtil.success(report);
    }

    @Override
    public Result<MorningEveningRankReport> getMorningEveningRankReport(FestivalTrafficRequest request) {
        // 日期必传
        String date = request.getDate();
        if (StringUtils.isEmpty(date)) {
            return ResultUtil.fail("早晚流量日期必传");
        }
        MorningEveningRankReport report = new MorningEveningRankReport();
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 开始时间是这一天的0点0分0秒
        String startTime = date + " 00:00:00";
        request.setStartTime(startTime);
        // 结束时间是这一天的23点59分59秒
        String endTime = date + " 23:59:59";
        request.setEndTime(endTime);
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 这一天的早高峰开始时间
        String morningStartTime = date + " " + ProjectConstant.EARLY_PEAK_START_TIME;
        Date morningStartDateTime = DateUtil.parse(morningStartTime);
        // 这一天的早高峰结束时间
        String morningEndTime = date + " " + ProjectConstant.EARLY_PEAK_END_TIME;
        Date morningEndDateTime = DateUtil.parse(morningEndTime);
        // 这一天的晚高峰开始时间
        String lateStartTime = date + " " + ProjectConstant.LATE_PEAK_START_TIME;
        Date lateStartDateTime = DateUtil.parse(lateStartTime);
        // 这一天的晚高峰结束时间
        String lateEndTime = date + " " + ProjectConstant.LATE_PEAK_END_TIME;
        Date lateEndDateTime = DateUtil.parse(lateEndTime);
        // 查询这一天范围内的数据
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlowDetail(request);
        /**
         * 早高峰总流量计算
         */
        // 早高峰数据
        List<GantryHourFlowWideVO> morningRecords = records.stream()
                .filter(item ->
                        item.getTime() != null &&
                        item.getTime().compareTo(morningStartDateTime) >= 0 &&
                        item.getTime().compareTo(morningEndDateTime) < 0)
                .collect(Collectors.toList());
        // 将同一个门架下的流量字段合并
        List<GantryHourFlowWideVO> processMorningRecords = this.processGantryRecords(morningRecords);
        List<MorningEveningRankReport.MorningEveningReport> morningTotalFlowList = new ArrayList<>();
        // 分路段计算总流量
        List<RoadFlowCalculateVO> morningCalculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processMorningRecords, ProjectConstant.TOTAL_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> morningRoadTotalFlowMap = morningCalculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        // 算流量要一条一条路算
        for (String roadName : morningRoadTotalFlowMap.keySet()) {
            MorningEveningRankReport.MorningEveningReport morningReport = new MorningEveningRankReport.MorningEveningReport();
            // 道路名称
            morningReport.setRoad(roadName);
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = morningRoadTotalFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int totalFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int totalFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadTotalFlow = totalFlowUp + totalFlowDown;
            morningReport.setTotalFlow(roadTotalFlow);
            morningTotalFlowList.add(morningReport);
        }
        report.setMorningFlowList(morningTotalFlowList);
        /**
         * 晚高峰总流量计算
         */
        // 晚高峰数据
        List<GantryHourFlowWideVO> eveningRecords = records.stream()
                .filter(item ->
                        item.getTime() != null &&
                        item.getTime().compareTo(lateStartDateTime) >= 0 &&
                        item.getTime().compareTo(lateEndDateTime) < 0)
                .collect(Collectors.toList());
        List<GantryHourFlowWideVO> processEveningRecords = this.processGantryRecords(eveningRecords);
        List<MorningEveningRankReport.MorningEveningReport> eveningTotalFlowList = new ArrayList<>();
        // 分路段计算总流量
        List<RoadFlowCalculateVO> eveningCalculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processEveningRecords, ProjectConstant.TOTAL_FLOW);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> eveningRoadTotalFlowMap = eveningCalculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        // 算流量要一条一条路算
        for (String roadName : eveningRoadTotalFlowMap.keySet()) {
            MorningEveningRankReport.MorningEveningReport eveningReport = new MorningEveningRankReport.MorningEveningReport();
            // 道路名称
            eveningReport.setRoad(roadName);
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = eveningRoadTotalFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int totalFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int totalFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadTotalFlow = totalFlowUp + totalFlowDown;
            eveningReport.setTotalFlow(roadTotalFlow);
            eveningTotalFlowList.add(eveningReport);
        }
        report.setEveningFlowList(eveningTotalFlowList);
        return ResultUtil.success(report);
    }

    @Override
    public Result<List<MorningEveningHourReport>> getMorningEveningHourReport(FestivalTrafficRequest request) {
        // 日期必传
        String date = request.getDate();
        if (StringUtils.isEmpty(date)) {
            return ResultUtil.fail("早晚流量日期必传");
        }
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 开始时间是这一天的0点0分0秒
        String startTime = date + " 00:00:00";
        request.setStartTime(startTime);
        // 结束时间是这一天的23点59分59秒
        String endTime = date + " 23:59:59";
        request.setEndTime(endTime);
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 查询这个路段所包含的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .eq(StringUtils.isNotEmpty(road), AMjHxl::getRoad, road)
        );
        // 设置门架id
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 查询这一天范围内的数据
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlowDetail(request);
        List<MorningEveningHourReport> reportList = new ArrayList<>();
        if (CollectionUtil.isEmpty(records)) {
            return ResultUtil.success(reportList);
        }
        // 根据开始时间、结束时间、时间类型生成时间点列表
        List<String> timePointList = DateTimeUtil.generateTimeList(startTime, endTime, ProjectConstant.HOUR);
        for (int i = 0; i < timePointList.size() - 1; i++) {
            MorningEveningHourReport reportItem = new MorningEveningHourReport();
            // 表示第几个小时
            reportItem.setTimePoint(String.valueOf(i));
            // 当前时间点
            String timePoint = timePointList.get(i);
            Date timePointDate = DateUtil.parse(timePoint);
            // 下一个时间点
            String nextTimePoint = timePointList.get(i + 1);
            Date nextTimePointDate = DateUtil.parse(nextTimePoint);
            // 过滤得到介于这两个时间点内的数据
            List<GantryHourFlowWideVO> itemRecords = records.stream()
                    .filter(item ->
                            item.getTime() != null &&
                            item.getTime().compareTo(timePointDate) >= 0 &&
                            item.getTime().compareTo(nextTimePointDate) < 0)
                    .collect(Collectors.toList());
            // 总流量
            int totalFlow = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, ProjectConstant.TOTAL_FLOW);
            reportItem.setTotalFlow(totalFlow);
            // 一型客车流量
            int vhc1 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC1.getField());
            reportItem.setVhc1(vhc1);
            // 二型客车流量
            int vhc2 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC2.getField());
            reportItem.setVhc2(vhc2);
            // 三型客车流量
            int vhc3 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC3.getField());
            reportItem.setVhc3(vhc3);
            // 四型客车流量
            int vhc4 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC4.getField());
            reportItem.setVhc4(vhc4);
            // 一型货车流量
            int vhc11 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC11.getField());
            reportItem.setVhc11(vhc11);
            // 二型货车流量
            int vhc12 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC12.getField());
            reportItem.setVhc12(vhc12);
            // 三型货车流量
            int vhc13 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC13.getField());
            reportItem.setVhc13(vhc13);
            // 四型货车流量
            int vhc14 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC14.getField());
            reportItem.setVhc14(vhc14);
            // 五型货车流量
            int vhc15 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC15.getField());
            reportItem.setVhc15(vhc15);
            // 六型货车流量
            int vhc16 = this.getAllRoadFlowByCarTypeAndTimePeriod(request, gantryRoadAreaInfoMap, itemRecords, CarTypeEnum.VHC16.getField());
            reportItem.setVhc16(vhc16);
            reportList.add(reportItem);
        }
        return ResultUtil.success(reportList);
    }

    @Override
    public Result<CrossOverviewStatisticReport> getMorningEveningCarTypeReport(FestivalTrafficRequest request) {
        // 日期必传
        String date = request.getDate();
        if (StringUtils.isEmpty(date)) {
            return ResultUtil.fail("早晚流量日期必传");
        }
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 获取道路编码-门架id映射
        Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 获取区域-门架id映射
        Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
        // 门架id-GantryRoadAreaInfo映射
        Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
        // 开始时间是这一天的0点0分0秒
        String startTime = date + " 00:00:00";
        request.setStartTime(startTime);
        // 结束时间是这一天的23点59分59秒
        String endTime = date + " 23:59:59";
        request.setEndTime(endTime);
        // 道路
        String road = request.getRoad();
        if (StringUtils.isNotEmpty(road)) {
            List<String> roadGantryIds = roadMap.get(road);
            request.setRoadGantryIds(roadGantryIds);
        }
        // 区域
        String area = request.getArea();
        if (StringUtils.isNotEmpty(area)) {
            List<String> areaGantryIds = areaMap.get(area);
            request.setAreaGantryIds(areaGantryIds);
        }
        // 查询这个路段所包含的门架id列表
        List<AMjHxl> list = aMjHxlService.list(new LambdaQueryWrapper<AMjHxl>()
                .eq(StringUtils.isNotEmpty(road), AMjHxl::getRoad, road)
        );
        // 设置门架id
        request.setGantryIds(list.stream().map(AMjHxl::getMjid).filter(Objects::nonNull).collect(Collectors.toList()));
        // 查询这一天范围内的数据
        List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
        CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
        if (CollectionUtil.isEmpty(records)) {
            return ResultUtil.success(report);
        }
        // 上行数据
        List<GantryHourFlowWideVO> upRecords = records.stream()
                .filter(record -> ProjectConstant.UP.equals(record.getDirection()))
                .collect(Collectors.toList());
        // 下行数据
        List<GantryHourFlowWideVO> downRecords = records.stream()
                .filter(record -> ProjectConstant.DOWN.equals(record.getDirection()))
                .collect(Collectors.toList());
        // 1型客车
        List<RoadFlowCalculateVO> calculateBus1UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC1.getField());
        int bus1UpFlow = this.calculateRoadFlow(calculateBus1UpList);
        List<RoadFlowCalculateVO> calculateBus1DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC1.getField());
        int bus1DownFlow = this.calculateRoadFlow(calculateBus1DownList);
        int bus1Flow = bus1UpFlow + bus1DownFlow;
        report.setVhc1(bus1Flow);
        report.setUpVhc1(bus1UpFlow);
        report.setDownVhc1(bus1DownFlow);
        // 2型客车
        List<RoadFlowCalculateVO> calculateBus2UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC2.getField());
        int bus2UpFlow = this.calculateRoadFlow(calculateBus2UpList);
        List<RoadFlowCalculateVO> calculateBus2DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC2.getField());
        int bus2DownFlow = this.calculateRoadFlow(calculateBus2DownList);
        int bus2Flow = bus2UpFlow + bus2DownFlow;
        report.setVhc2(bus2Flow);
        report.setUpVhc2(bus2UpFlow);
        report.setDownVhc2(bus2DownFlow);
        // 3型客车
        List<RoadFlowCalculateVO> calculateBus3UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC3.getField());
        int bus3UpFlow = this.calculateRoadFlow(calculateBus3UpList);
        List<RoadFlowCalculateVO> calculateBus3DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC3.getField());
        int bus3DownFlow = this.calculateRoadFlow(calculateBus3DownList);
        int bus3Flow = bus3UpFlow + bus3DownFlow;
        report.setVhc3(bus3Flow);
        report.setUpVhc3(bus3UpFlow);
        report.setDownVhc3(bus3DownFlow);
        // 4型客车
        List<RoadFlowCalculateVO> calculateBus4UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC4.getField());
        int bus4UpFlow = this.calculateRoadFlow(calculateBus4UpList);
        List<RoadFlowCalculateVO> calculateBus4DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC4.getField());
        int bus4DownFlow = this.calculateRoadFlow(calculateBus4DownList);
        int bus4Flow = bus4UpFlow + bus4DownFlow;
        report.setVhc4(bus4Flow);
        report.setUpVhc4(bus4UpFlow);
        report.setDownVhc4(bus4DownFlow);
        // 1型货车
        List<RoadFlowCalculateVO> calculateTrunk1UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC11.getField());
        int trunk1UpFlow = this.calculateRoadFlow(calculateTrunk1UpList);
        List<RoadFlowCalculateVO> calculateTrunk1DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC11.getField());
        int trunk1DownFlow = this.calculateRoadFlow(calculateTrunk1DownList);
        int trunk1Flow = trunk1UpFlow + trunk1DownFlow;
        report.setVhc11(trunk1Flow);
        report.setUpVhc11(trunk1UpFlow);
        report.setDownVhc11(trunk1DownFlow);
        // 2型货车
        List<RoadFlowCalculateVO> calculateTrunk2UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC12.getField());
        int trunk2UpFlow = this.calculateRoadFlow(calculateTrunk2UpList);
        List<RoadFlowCalculateVO> calculateTrunk2DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC12.getField());
        int trunk2DownFlow = this.calculateRoadFlow(calculateTrunk2DownList);
        int trunk2Flow = trunk2UpFlow + trunk2DownFlow;
        report.setVhc12(trunk2Flow);
        report.setUpVhc12(trunk2UpFlow);
        report.setDownVhc12(trunk2DownFlow);
        // 3型货车
        List<RoadFlowCalculateVO> calculateTrunk3UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC13.getField());
        int trunk3UpFlow = this.calculateRoadFlow(calculateTrunk3UpList);
        List<RoadFlowCalculateVO> calculateTrunk3DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC13.getField());
        int trunk3DownFlow = this.calculateRoadFlow(calculateTrunk3DownList);
        int trunk3Flow = trunk3UpFlow + trunk3DownFlow;
        report.setVhc13(trunk3Flow);
        report.setUpVhc13(trunk3UpFlow);
        report.setDownVhc13(trunk3DownFlow);
        // 4型货车
        List<RoadFlowCalculateVO> calculateTrunk4UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC14.getField());
        int trunk4UpFlow = this.calculateRoadFlow(calculateTrunk4UpList);
        List<RoadFlowCalculateVO> calculateTrunk4DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC14.getField());
        int trunk4DownFlow = this.calculateRoadFlow(calculateTrunk4DownList);
        int trunk4Flow = trunk4UpFlow + trunk4DownFlow;
        report.setVhc14(trunk4Flow);
        report.setUpVhc14(trunk4UpFlow);
        report.setDownVhc14(trunk4DownFlow);
        // 5型货车
        List<RoadFlowCalculateVO> calculateTrunk5UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC15.getField());
        int trunk5UpFlow = this.calculateRoadFlow(calculateTrunk5UpList);
        List<RoadFlowCalculateVO> calculateTrunk5DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC15.getField());
        int trunk5DownFlow = this.calculateRoadFlow(calculateTrunk5DownList);
        int trunk5Flow = trunk5UpFlow + trunk5DownFlow;
        report.setVhc15(trunk5Flow);
        report.setUpVhc15(trunk5UpFlow);
        report.setDownVhc15(trunk5DownFlow);
        // 6型货车
        List<RoadFlowCalculateVO> calculateTrunk6UpList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, upRecords, CarTypeEnum.VHC16.getField());
        int trunk6UpFlow = this.calculateRoadFlow(calculateTrunk6UpList);
        List<RoadFlowCalculateVO> calculateTrunk6DownList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, downRecords, CarTypeEnum.VHC16.getField());
        int trunk6DownFlow = this.calculateRoadFlow(calculateTrunk6DownList);
        int trunk6Flow = trunk6UpFlow + trunk6DownFlow;
        report.setVhc16(trunk6Flow);
        report.setUpVhc16(trunk6UpFlow);
        report.setDownVhc16(trunk6DownFlow);
        return ResultUtil.success(report);
    }

    /**
     * 获取所有道路在指定时间段内和指定车型的总流量
     * @param request
     * @param gantryRoadAreaInfoMap
     * @param itemRecords
     * @param carType
     * @return
     */
    private int getAllRoadFlowByCarTypeAndTimePeriod(FestivalTrafficRequest request, Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap, List<GantryHourFlowWideVO> itemRecords, String carType) {
        // 将同一个门架下的流量字段合并
        List<GantryHourFlowWideVO> processRecords = this.processGantryRecords(itemRecords);
        // 分路段计算总流量
        List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processRecords, carType);
        // 路段编号-List<RoadFlowCalculateVO>映射
        Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
        int totalFlow = 0;
        // 算流量要一条一条路算
        for (String roadName : roadTotalFlowMap.keySet()) {
            // 对应列表
            List<RoadFlowCalculateVO> calculateList = roadTotalFlowMap.get(roadName);
            // 上行列表
            List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 下行列表
            List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                    .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                    .collect(Collectors.toList());
            // 计算收费站之间的上行流量
            int totalFlowUp = this.calculateRoadFlow(upFlowList);
            // 计算收费站之间的下行流量
            int totalFlowDown = this.calculateRoadFlow(downFlowList);
            // 总流量 = 上行流量 + 下行流量
            int roadTotalFlow = totalFlowUp + totalFlowDown;
            totalFlow += roadTotalFlow;
        }
        return totalFlow;
    }

    /**
     * 获取节假日单日流量
     * @param request
     * @param holidayType
     * @param year
     * @param analysisType
     * @return
     */
    private List<FestivalSingleFlowReport> getFestivalSingleDailyFlow(FestivalTrafficRequest request, Integer holidayType, Integer year, String analysisType) {
        List<FestivalSingleFlowReport> reportList = new ArrayList<>();
        // 根据年份节假日类型查询开始和结束时间
        HolidayRequest holidayRequest = new HolidayRequest();
        holidayRequest.setType(holidayType);
        holidayRequest.setYear(year);
        // 今年该节假日的时间列表
        List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
        if (CollectionUtil.isNotEmpty(holidayDateList)) {
            // 开始时间是第一项
            String startTime = holidayDateList.get(0) + " 00:00:00";
            request.setStartTime(startTime);
            // 结束时间是最后一项的23点59分59秒
            String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
            request.setEndTime(endTime);
            // 获取所有信息
            List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
            // 获取道路编码-门架id映射
            Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
            // 获取区域-门架id映射
            Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
            // 门架id-GantryRoadAreaInfo映射
            Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
            // 道路
            String road = request.getRoad();
            if (StringUtils.isNotEmpty(road)) {
                List<String> roadGantryIds = roadMap.get(road);
                request.setRoadGantryIds(roadGantryIds);
            }
            // 区域
            String area = request.getArea();
            if (StringUtils.isNotEmpty(area)) {
                List<String> areaGantryIds = areaMap.get(area);
                request.setAreaGantryIds(areaGantryIds);
            }
            // 按请求查询数据(查询精确到门架)
            List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlowDetail(request);
            if (CollectionUtil.isNotEmpty(records)) {
                // 遍历holidayDateList依次得到每一天的数据
                for (int i = 0; i < holidayDateList.size(); i++) {
                    String date = holidayDateList.get(i);
                    FestivalSingleFlowReport report = new FestivalSingleFlowReport();
                    // 时间
                    if (ProjectConstant.SINGLE.equals(analysisType)) {
                        // 如果是单个节假日的分析横坐标是日期
                        report.setTimePoint(date);
                    } else if (ProjectConstant.MULTIPLE.equals(analysisType)) {
                        // 如果是多个节假日的分析横坐标是i+1
                        report.setTimePoint(String.valueOf(i + 1));
                    }
                    // 开始时间是0点0分0秒
                    String queryStartTime = date + " 00:00:00";
                    // 结束时间是23点59分59秒
                    String queryEndTime = date + " 23:59:59";
                    // 过滤得到在这个时间段内的数据
                    List<GantryHourFlowWideVO> itemRecords = records.stream()
                            .filter(record ->
                                    record.getTime() != null &&
                                    record.getTime().after(DateUtil.parse(queryStartTime)) &&
                                    record.getTime().before(DateUtil.parse(queryEndTime)))
                            .collect(Collectors.toList());
                    // 将同一个门架下的流量字段合并
                    List<GantryHourFlowWideVO> processRecords = this.processGantryRecords(itemRecords);
                    // 分路段计算总流量
                    List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, processRecords, ProjectConstant.TOTAL_FLOW);
                    // 路段编号-List<RoadFlowCalculateVO>映射
                    Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                            .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                    int totalFlow = 0;
                    // 算流量要一条一条路算
                    for (String roadName : roadTotalFlowMap.keySet()) {
                        // 对应列表
                        List<RoadFlowCalculateVO> calculateList = roadTotalFlowMap.get(roadName);
                        // 上行列表
                        List<RoadFlowCalculateVO> upFlowList = calculateList.stream()
                                .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                                .collect(Collectors.toList());
                        // 下行列表
                        List<RoadFlowCalculateVO> downFlowList = calculateList.stream()
                                .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                                .collect(Collectors.toList());
                        // 计算收费站之间的上行流量
                        int totalFlowUp = this.calculateRoadFlow(upFlowList);
                        // 计算收费站之间的下行流量
                        int totalFlowDown = this.calculateRoadFlow(downFlowList);
                        // 总流量 = 上行流量 + 下行流量
                        int roadTotalFlow = totalFlowUp + totalFlowDown;
                        totalFlow += roadTotalFlow;
                    }
                    report.setTotalFlow(totalFlow);
                    reportList.add(report);
                }
            }
        }
        return reportList;
    }

    /**
     * 路段排行单个节假日排行
     * @param request
     * @param year
     * @param holidayType
     * @return
     */
    private List<FestivalTrafficRankReport> getFestivalRoadRankReport(FestivalTrafficRequest request, Integer year, Integer holidayType) {
        List<FestivalTrafficRankReport> reportList = new ArrayList<>();
        // 根据年份节假日类型查询开始和结束时间
        HolidayRequest holidayRequest = new HolidayRequest();
        holidayRequest.setType(holidayType);
        holidayRequest.setYear(year);
        // 今年该节假日的时间列表
        List<String> holidayDateList = holidayInfoService.getHolidayByYearAndType(holidayRequest);
        if (CollectionUtil.isNotEmpty(holidayDateList)) {
            // 开始时间是第一项
            String startTime = holidayDateList.get(0) + " 00:00:00";
            request.setStartTime(startTime);
            // 结束时间是最后一项
            String endTime = holidayDateList.get(holidayDateList.size() - 1) + " 23:59:59";
            request.setEndTime(endTime);
            // 获取所有信息
            List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
            // 获取道路编码-门架id映射
            Map<String, List<String>> roadMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.groupingBy(GantryRoadAreaInfo::getRoadCode, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
            // 获取区域-门架id映射
            Map<String, List<String>> areaMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.groupingBy(GantryRoadAreaInfo::getAreaName, Collectors.mapping(GantryRoadAreaInfo::getGantryId, Collectors.toList())));
            // 门架id-GantryRoadAreaInfo映射
            Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap = gantryRoadAreaInfos.stream()
                    .collect(Collectors.toMap(GantryRoadAreaInfo::getGantryId, gantryRoadAreaInfo -> gantryRoadAreaInfo));
            // 道路
            String road = request.getRoad();
            if (StringUtils.isNotEmpty(road)) {
                List<String> roadGantryIds = roadMap.get(road);
                request.setRoadGantryIds(roadGantryIds);
            }
            // 区域
            String area = request.getArea();
            if (StringUtils.isNotEmpty(area)) {
                List<String> areaGantryIds = areaMap.get(area);
                request.setAreaGantryIds(areaGantryIds);
            }
            // 按请求查询数据(查询精确到门架)
            List<GantryHourFlowWideVO> records = gantryHourFlowWideMapper.getRoadFlow(request);
            if (CollectionUtil.isNotEmpty(records)) {
                // 分路段计算总流量
                List<RoadFlowCalculateVO> calculateTotalList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TOTAL_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadTotalFlowMap = calculateTotalList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                // 算流量要一条一条路算
                for (String roadName : roadTotalFlowMap.keySet()) {
                    FestivalTrafficRankReport report = new FestivalTrafficRankReport();
                    // 对应列表
                    List<RoadFlowCalculateVO> list = roadTotalFlowMap.get(roadName);
                    // 这一年该节日的上行列表
                    List<RoadFlowCalculateVO> upFlowList = list.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 这一年该节日的下行列表
                    List<RoadFlowCalculateVO> downFlowList = list.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int totalFlowUp = this.calculateRoadFlow(upFlowList);
                    // 计算收费站之间的下行流量
                    int totalFlowDown = this.calculateRoadFlow(downFlowList);
                    // 总流量 = 上行流量 + 下行流量
                    int totalFlow = totalFlowUp + totalFlowDown;
                    report.setTotalFlow(totalFlow);
                    report.setRoadName(roadName);
                    reportList.add(report);
                }
                // 分路段计算客车总流量
                List<RoadFlowCalculateVO> calculateBusList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.BUS_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadBusFlowMap = calculateBusList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                // 算流量要一条一条路算
                for (String roadName : roadBusFlowMap.keySet()) {
                    FestivalTrafficRankReport report = null;
                    for (FestivalTrafficRankReport item : reportList) {
                        if (roadName.equals(item.getRoadName())) {
                            report = item;
                            break;
                        }
                    }
                    // 对应列表
                    List<RoadFlowCalculateVO> list = roadBusFlowMap.get(roadName);
                    // 这一年该节日的客车上行列表
                    List<RoadFlowCalculateVO> busUpFlowList = list.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 这一年该节日的客车下行列表
                    List<RoadFlowCalculateVO> busDownFlowList = list.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int busFlowUp = this.calculateRoadFlow(busUpFlowList);
                    // 计算收费站之间的下行流量
                    int busFlowDown = this.calculateRoadFlow(busDownFlowList);
                    int busFlow = busFlowUp + busFlowDown;
                    if (report != null) {
                        report.setBusFlow(busFlow);
                    }
                }
                // 分路段计算货车总流量
                List<RoadFlowCalculateVO> calculateTruckList = this.getFlowCalculateList(request, gantryRoadAreaInfoMap, records, ProjectConstant.TRUCK_FLOW);
                // 路段编号-List<RoadFlowCalculateVO>映射
                Map<String, List<RoadFlowCalculateVO>> roadTruckFlowMap = calculateTruckList.stream()
                        .collect(Collectors.groupingBy(RoadFlowCalculateVO::getRoadName));
                for (String roadName : roadTruckFlowMap.keySet()) {
                    FestivalTrafficRankReport report = null;
                    for (FestivalTrafficRankReport item : reportList) {
                        if (roadName.equals(item.getRoadName())) {
                            report = item;
                            break;
                        }
                    }
                    // 对应列表
                    List<RoadFlowCalculateVO> list = roadTruckFlowMap.get(roadName);
                    // 这一年该节日的货车上行列表
                    List<RoadFlowCalculateVO> truckUpFlowList = list.stream()
                            .filter(item -> ProjectConstant.UP.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 这一年该节日的货车下行列表
                    List<RoadFlowCalculateVO> truckDownFlowList = list.stream()
                            .filter(item -> ProjectConstant.DOWN.equals(item.getDirection()))
                            .collect(Collectors.toList());
                    // 计算收费站之间的上行流量
                    int truckFlowUp = this.calculateRoadFlow(truckUpFlowList);
                    // 计算收费站之间的下行流量
                    int truckFlowDown = this.calculateRoadFlow(truckDownFlowList);
                    int truckFlow = truckFlowUp + truckFlowDown;
                    if (report != null) {
                        report.setTruckFlow(truckFlow);
                    }
                }
            }
        }
        return reportList;
    }

    /**
     * 判断两个门架是否在同一条路上
     * @param startStationId
     * @param endStationId
     * @return
     */
    private boolean isInSameRoad(String startStationId, String endStationId) {
        // 获取所有收费站信息
        List<StationRoadAreaInfo> stationList = stationRoadAreaInfoService.list();
        // stationId-roadCode映射
        Map<String, String> stationRoadCodeMap = stationList.stream()
                .collect(Collectors.toMap(StationRoadAreaInfo::getStationId, StationRoadAreaInfo::getRoadCode));
        // 当且仅当两个收费站对应的路线码相同时,才能判定两个门架在同条路上
        return stationRoadCodeMap.containsKey(startStationId) &&
                stationRoadCodeMap.containsKey(endStationId) &&
                StringUtils.equals(stationRoadCodeMap.get(startStationId), stationRoadCodeMap.get(endStationId));
    }

    /**
     * 创建报告项
     * @param reports
     * @param record
     */
    private void createReportItem(List<TrafficRankReport> reports, GantryHourFlowWideVO record) {
        TrafficRankReport report = new TrafficRankReport();
        // 起止门架
        report.setStartEndPlace(record.getStartEndPlace());
        // 客车流量
        report.setBusFlow(record.getVhc1() + record.getVhc2() + record.getVhc3() + record.getVhc4());
        // 货车流量
        report.setTruckFlow(record.getVhc11() + record.getVhc12() + record.getVhc13() + record.getVhc14() + record.getVhc15() + record.getVhc16());
        // 总流量
        report.setTotalFlow(report.getBusFlow() + report.getTruckFlow());
        // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
        report.setVhc1(record.getVhc1());
        report.setVhc2(record.getVhc2());
        report.setVhc3(record.getVhc3());
        report.setVhc4(record.getVhc4());
        report.setVhc11(record.getVhc11());
        report.setVhc12(record.getVhc12());
        report.setVhc13(record.getVhc13());
        report.setVhc14(record.getVhc14());
        report.setVhc15(record.getVhc15());
        report.setVhc16(record.getVhc16());
        report.setVhc21(record.getVhc21());
        report.setVhc22(record.getVhc22());
        report.setVhc23(record.getVhc23());
        report.setVhc24(record.getVhc24());
        report.setVhc25(record.getVhc25());
        report.setVhc26(record.getVhc26());
        reports.add(report);
    }

    /**
     * 创建报告项
     * @param reports
     * @param record
     */
    private void createReportItemInGantryFlow(List<CrossOverviewStatisticReport> reports, GantryHourFlowWideVO record) {
        CrossOverviewStatisticReport report = new CrossOverviewStatisticReport();
        // 日期
        String date = DateUtil.format(record.getTime(), "yyyy-MM-dd");
        report.setDate(date);
        // 经度
        report.setLon(record.getLon());
        // 纬度
        report.setLat(record.getLat());
        // 起止门架
        report.setStartEndPlace(record.getStartEndPlace());
        // 客车流量
        report.setBusFlow(record.getVhc1() + record.getVhc2() + record.getVhc3() + record.getVhc4());
        // 货车流量
        report.setTruckFlow(record.getVhc11() + record.getVhc12() + record.getVhc13() + record.getVhc14() + record.getVhc15() + record.getVhc16());
        // 总流量
        report.setTotalFlow(report.getBusFlow() + report.getTruckFlow());
        // 方向
        String direction = record.getDirection();
        if (ProjectConstant.UP.equals(direction)) {
            report.setUpFlow(report.getTotalFlow());
        } else if (ProjectConstant.DOWN.equals(direction)) {
            report.setDownFlow(report.getTotalFlow());
        }
        // 下述字段用于单独筛选某种车型的时候展示，让前端自主判断
        report.setVhc1(record.getVhc1());
        report.setVhc2(record.getVhc2());
        report.setVhc3(record.getVhc3());
        report.setVhc4(record.getVhc4());
        report.setVhc11(record.getVhc11());
        report.setVhc12(record.getVhc12());
        report.setVhc13(record.getVhc13());
        report.setVhc14(record.getVhc14());
        report.setVhc15(record.getVhc15());
        report.setVhc16(record.getVhc16());
        report.setVhc21(record.getVhc21());
        report.setVhc22(record.getVhc22());
        report.setVhc23(record.getVhc23());
        report.setVhc24(record.getVhc24());
        report.setVhc25(record.getVhc25());
        report.setVhc26(record.getVhc26());
        if (ProjectConstant.UP.equals(direction)) {
            report.setUpVhc1(record.getVhc1());
            report.setUpVhc2(record.getVhc2());
            report.setUpVhc3(record.getVhc3());
            report.setUpVhc4(record.getVhc4());
            report.setUpVhc11(record.getVhc11());
            report.setUpVhc12(record.getVhc12());
            report.setUpVhc13(record.getVhc13());
            report.setUpVhc14(record.getVhc14());
            report.setUpVhc15(record.getVhc15());
            report.setUpVhc16(record.getVhc16());
            report.setUpVhc21(record.getVhc21());
            report.setUpVhc22(record.getVhc22());
            report.setUpVhc23(record.getVhc23());
            report.setUpVhc24(record.getVhc24());
            report.setUpVhc25(record.getVhc25());
            report.setUpVhc26(record.getVhc26());
        } else if (ProjectConstant.DOWN.equals(direction)) {
            report.setDownVhc1(record.getVhc1());
            report.setDownVhc2(record.getVhc2());
            report.setDownVhc3(record.getVhc3());
            report.setDownVhc4(record.getVhc4());
            report.setDownVhc11(record.getVhc11());
            report.setDownVhc12(record.getVhc12());
            report.setDownVhc13(record.getVhc13());
            report.setDownVhc14(record.getVhc14());
            report.setDownVhc15(record.getVhc15());
            report.setDownVhc16(record.getVhc16());
            report.setDownVhc21(record.getVhc21());
            report.setDownVhc22(record.getVhc22());
            report.setDownVhc23(record.getVhc23());
            report.setDownVhc24(record.getVhc24());
            report.setDownVhc25(record.getVhc25());
            report.setDownVhc26(record.getVhc26());
        }
        reports.add(report);
    }

    /**
     * 判断是否已存在
     * @param reports
     * @param record
     * @return
     */
    private boolean isExit(List<TrafficRankReport> reports, GantryHourFlowWideVO record) {
        for (TrafficRankReport report : reports) {
            String reportStartEndPlace = report.getStartEndPlace();
            String recordStartEndPlace = record.getStartEndPlace();
            // -之前
            String reportStart = reportStartEndPlace.split(ProjectConstant.MINUS)[0];
            String recordStart = recordStartEndPlace.split(ProjectConstant.MINUS)[0];
            // -之后
            String reportEnd = reportStartEndPlace.split(ProjectConstant.MINUS)[1];
            String recordEnd = recordStartEndPlace.split(ProjectConstant.MINUS)[1];
            // 如果开始=开始,结束=结束,那么就是同一个
            if (StringUtils.equals(recordStart, reportStart) && StringUtils.equals(recordEnd, reportEnd)) {
                return true;
            }
            // 如果开始=结束,结束=开始,那么也是同一个
            if (StringUtils.equals(recordStart, reportEnd) && StringUtils.equals(recordEnd, reportStart)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否已存在
     * @param reports
     * @param record
     * @return
     */
    private boolean isExitInGantryFlow(List<CrossOverviewStatisticReport> reports, GantryHourFlowWideVO record) {
        for (CrossOverviewStatisticReport report : reports) {
            String reportStartEndPlace = report.getStartEndPlace();
            String recordStartEndPlace = record.getStartEndPlace();
            // -之前
            String reportStart = reportStartEndPlace.split(ProjectConstant.MINUS)[0];
            String recordStart = recordStartEndPlace.split(ProjectConstant.MINUS)[0];
            // -之后
            String reportEnd = reportStartEndPlace.split(ProjectConstant.MINUS)[1];
            String recordEnd = recordStartEndPlace.split(ProjectConstant.MINUS)[1];
            // 如果开始=开始,结束=结束,那么就是同一个
            if (StringUtils.equals(recordStart, reportStart) && StringUtils.equals(recordEnd, reportEnd)) {
                return true;
            }
            // 如果开始=结束,结束=开始,那么也是同一个
            if (StringUtils.equals(recordStart, reportEnd) && StringUtils.equals(recordEnd, reportStart)) {
                return true;
            }
        }
        return false;
    }

    private TrafficRankReport getExitReportItem(List<TrafficRankReport> reports, GantryHourFlowWideVO record) {
        for (TrafficRankReport report : reports) {
            String reportStartEndPlace = report.getStartEndPlace();
            String recordStartEndPlace = record.getStartEndPlace();
            // -之前
            String reportStart = reportStartEndPlace.split(ProjectConstant.MINUS)[0];
            String recordStart = recordStartEndPlace.split(ProjectConstant.MINUS)[0];
            // -之后
            String reportEnd = reportStartEndPlace.split(ProjectConstant.MINUS)[1];
            String recordEnd = recordStartEndPlace.split(ProjectConstant.MINUS)[1];
            // 如果开始=开始,结束=结束,那么就是同一个
            if (StringUtils.equals(recordStart, reportStart) && StringUtils.equals(recordEnd, reportEnd)) {
                return report;
            }
            // 如果开始=结束,结束=开始,那么也是同一个
            if (StringUtils.equals(recordStart, reportEnd) && StringUtils.equals(recordEnd, reportStart)) {
                return report;
            }
        }
        return new TrafficRankReport();
    }

    private CrossOverviewStatisticReport getExitReportItemInGantryFlow(List<CrossOverviewStatisticReport> reports, GantryHourFlowWideVO record) {
        for (CrossOverviewStatisticReport report : reports) {
            String reportStartEndPlace = report.getStartEndPlace();
            String recordStartEndPlace = record.getStartEndPlace();
            // -之前
            String reportStart = reportStartEndPlace.split(ProjectConstant.MINUS)[0];
            String recordStart = recordStartEndPlace.split(ProjectConstant.MINUS)[0];
            // -之后
            String reportEnd = reportStartEndPlace.split(ProjectConstant.MINUS)[1];
            String recordEnd = recordStartEndPlace.split(ProjectConstant.MINUS)[1];
            // 如果开始=开始,结束=结束,那么就是同一个
            if (StringUtils.equals(recordStart, reportStart) && StringUtils.equals(recordEnd, reportEnd)) {
                return report;
            }
            // 如果开始=结束,结束=开始,那么也是同一个
            if (StringUtils.equals(recordStart, reportEnd) && StringUtils.equals(recordEnd, reportStart)) {
                return report;
            }
        }
        return new CrossOverviewStatisticReport();
    }

    /**
     * 获取路段流量计算列表(需要对流量进行叠加处理)这里的records中每个门架只有一条数据
     * @param request
     * @param gantryRoadAreaInfoMap
     * @param records
     * @param flowType
     * @return
     */
    private List<RoadFlowCalculateVO> getFlowCalculateList(CommonRequest request, Map<String, GantryRoadAreaInfo> gantryRoadAreaInfoMap, List<GantryHourFlowWideVO> records, String flowType) {
        List<RoadFlowCalculateVO> calculateTotalList = new ArrayList<>();
        // 遍历数据项,首先对门架进行总流量计算
        for (GantryHourFlowWideVO record : records) {
            RoadFlowCalculateVO calculateVO = new RoadFlowCalculateVO();
            // 门架id
            String gantryId = record.getGrantryId();
            // 如果门架id为空,则跳过
            if (StringUtils.isBlank(gantryId)) {
                continue;
            }
            calculateVO.setGantryId(gantryId);
            Map<String, Integer> carTypeCountMap = CarTypeEnum.getSelectedCarTypeCountMap(request.getCarTypeChoose(), record);
            // 所选车型在单个门架的总流量
            int flow = carTypeCountMap.get(flowType);
            calculateVO.setFlow(flow);
            // 桩号数值
            GantryRoadAreaInfo gantryRoadAreaInfo = gantryRoadAreaInfoMap.get(gantryId);
            calculateVO.setPileNumValue(gantryRoadAreaInfo.getPileNumValue());
            // 方向
            calculateVO.setDirection(record.getDirection());
            // 路段编号
            calculateVO.setRoadName(record.getRoadName());
            calculateTotalList.add(calculateVO);
        }
        return calculateTotalList;
    }

    /**
     * 计算道路流量
     * 需要按方向计算并相加,总路段流量 = 上行路段流量 + 下行路段流量
     * @param calculateList
     * @return
     */
    private Integer calculateRoadFlow(List<RoadFlowCalculateVO> calculateList) {
        if (CollectionUtil.isEmpty(calculateList)) {
            return 0;
        }
        // 过滤得到所有主门架数据
        List<RoadFlowCalculateVO> mainCalculateList = calculateList.stream()
                // 判断方法是最后两位是10的就是主门架
                .filter(calculate -> StringUtils.endsWith(calculate.getGantryId(), ProjectConstant.MAIN_GANTRY_SUFFIX))
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(mainCalculateList)) {
            return 0;
        }
        // 如果主门架只有一个
        if (mainCalculateList.size() == 1) {
            // 直接返回主门架流量
            return mainCalculateList.get(0).getFlow();
        }
        // 遍历主门架列表,找出对应的副门架,移除所有副门架流量,并把副门架流量加到主门架流量上
        for (RoadFlowCalculateVO mainCalculate : mainCalculateList) {
            // 遍历所有门架列表
            for (RoadFlowCalculateVO calculate : calculateList) {
                // 主门架id最后两位之前
                String mainGantryIdBetweenLastTwo = mainCalculate.getGantryId().substring(0, mainCalculate.getGantryId().length() - 2);
                // 门架id最后两位之前
                String gantryIdBetweenLastTwo = calculate.getGantryId().substring(0, calculate.getGantryId().length() - 2);
                // 判断是否是副门架且是同个门架
                if (StringUtils.endsWith(calculate.getGantryId(), ProjectConstant.SUB_GANTRY_SUFFIX) && StringUtils.equals(mainGantryIdBetweenLastTwo, gantryIdBetweenLastTwo)) {
                    // 把副门架的流量加到主门架上
                    mainCalculate.setFlow(mainCalculate.getFlow() + calculate.getFlow());
                }
            }
        }
        // 对主门架的桩号数值进行排序,从小到大
        mainCalculateList.sort(Comparator.comparingInt(RoadFlowCalculateVO::getPileNumValue));
        // 开始计算calculateList对应路段的流量与距离乘积
        BigDecimal roadFlowPlusDistance = BigDecimal.valueOf(0);
        for (int i = 0; i < mainCalculateList.size() - 1; i++) {
            // 当前项
            RoadFlowCalculateVO current = mainCalculateList.get(i);
            // 当前项流量
            Integer currentFlow = current.getFlow();
            // 当前项桩号数值
            Integer currentPileNum = current.getPileNumValue();
            // 下一项
            RoadFlowCalculateVO next = mainCalculateList.get(i + 1);
            // 下一项流量
            Integer nextFlow = next.getFlow();
            // 下一项桩号数值
            Integer nextPileNum = next.getPileNumValue();
            // 桩号数值差(单位从米转化为千米)
            int pileNumDifference = nextPileNum - currentPileNum;
            BigDecimal pileNumDistance = new BigDecimal(pileNumDifference).divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
            // 流量之和
            int distanceFlowPlus = currentFlow + nextFlow;
            // 两点之间的流量 = (当前项流量 + 下一项流量) * (下一项桩号数值 - 当前项桩号数值) / 2
            BigDecimal distanceFlow = new BigDecimal(distanceFlowPlus).multiply(pileNumDistance).divide(new BigDecimal(2), 2, RoundingMode.HALF_UP);
            // 对roadFlowPlusDistance做累加
            roadFlowPlusDistance = roadFlowPlusDistance.add(distanceFlow);
        }
        // 第一个桩号数值
        Integer firstPileNum = mainCalculateList.get(0).getPileNumValue();
        // 最后一个桩号数值
        Integer lastPileNum = mainCalculateList.get(mainCalculateList.size() - 1).getPileNumValue();
        // 首尾桩号数值差(单位从米转化为千米)
        int pileNumDifference = lastPileNum - firstPileNum;
        BigDecimal pileNumDistance = new BigDecimal(pileNumDifference).divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
        // 路段流量 = calculateList对应路段的流量与距离乘积 / 首尾桩号数值的差
        BigDecimal roadFlow = roadFlowPlusDistance.divide(pileNumDistance, 2, RoundingMode.HALF_UP);
        return roadFlow.intValue();
    }

    /**
     * 获取道路编码-名称映射
     * @return
     */
    private Map<String, String> getRoadCodeNameMap() {
        // 获取所有信息
        List<GantryRoadAreaInfo> gantryRoadAreaInfos = gantryRoadAreaInfoService.list();
        // 道路编码-名称映射
        Map<String, String> roadNameMap = gantryRoadAreaInfos.stream()
                .collect(Collectors.toMap(
                        GantryRoadAreaInfo::getRoadCode,
                        GantryRoadAreaInfo::getRoadName,
                        (existing, replacement) -> existing // 当键重复时，保留已存在的值（第一个）
                ));
        // 所有收费站信息
        List<StationRoadAreaInfo> stationInfos = stationRoadAreaInfoService.list();
        // 道路编码-名称映射
        Map<String, String> roadCodeNameMap = stationInfos.stream()
                .collect(Collectors.toMap(
                        StationRoadAreaInfo::getRoadCode,
                        StationRoadAreaInfo::getRoadName,
                        (existing, replacement) -> existing // 当键重复时，保留已存在的值（第一个）
                ));
        // roadNameMap中放入roadCodeNameMap
        roadNameMap.putAll(roadCodeNameMap);
        return roadNameMap;
    }


    /**
     * 处理GantryHourFlowWideVO列表，对相同gantryId的记录进行合并，累加数值字段
     * @param records 原始数据列表
     * @return 处理后的数据列表，每个gantryId只保留一条记录
     */
    public List<GantryHourFlowWideVO> processGantryRecords(List<GantryHourFlowWideVO> records) {
        if (records == null || records.isEmpty()) {
            return new ArrayList<>();
        }

        // 按gantryId分组，并对每组数据进行合并处理
        Map<String, GantryHourFlowWideVO> mergedMap = new HashMap<>();

        for (GantryHourFlowWideVO record : records) {
            String gantryId = record.getGrantryId();

            if (mergedMap.containsKey(gantryId)) {
                // 如果已存在该gantryId的记录，则累加数值字段
                GantryHourFlowWideVO existingRecord = mergedMap.get(gantryId);
                // 将同一个门架下的数据合并
                this.mergeRecords(existingRecord, record);
            } else {
                // 如果不存在该gantryId的记录，则直接添加
                // 创建新的实例避免引用原始对象
                GantryHourFlowWideVO newRecord = this.copyRecord(record);
                mergedMap.put(gantryId, newRecord);
            }
        }

        return new ArrayList<>(mergedMap.values());
    }

    /**
     * 合并两条记录，将sourceRecord的数值字段累加到targetRecord中
     * @param targetRecord 目标记录
     * @param sourceRecord 源记录
     */
    private void mergeRecords(GantryHourFlowWideVO targetRecord, GantryHourFlowWideVO sourceRecord) {
        // 累加vhc相关字段
        targetRecord.setVhc1(addNullableIntegers(targetRecord.getVhc1(), sourceRecord.getVhc1()));
        targetRecord.setVhc2(addNullableIntegers(targetRecord.getVhc2(), sourceRecord.getVhc2()));
        targetRecord.setVhc3(addNullableIntegers(targetRecord.getVhc3(), sourceRecord.getVhc3()));
        targetRecord.setVhc4(addNullableIntegers(targetRecord.getVhc4(), sourceRecord.getVhc4()));
        targetRecord.setVhc11(addNullableIntegers(targetRecord.getVhc11(), sourceRecord.getVhc11()));
        targetRecord.setVhc12(addNullableIntegers(targetRecord.getVhc12(), sourceRecord.getVhc12()));
        targetRecord.setVhc13(addNullableIntegers(targetRecord.getVhc13(), sourceRecord.getVhc13()));
        targetRecord.setVhc14(addNullableIntegers(targetRecord.getVhc14(), sourceRecord.getVhc14()));
        targetRecord.setVhc15(addNullableIntegers(targetRecord.getVhc15(), sourceRecord.getVhc15()));
        targetRecord.setVhc16(addNullableIntegers(targetRecord.getVhc16(), sourceRecord.getVhc16()));
        targetRecord.setVhc21(addNullableIntegers(targetRecord.getVhc21(), sourceRecord.getVhc21()));
        targetRecord.setVhc22(addNullableIntegers(targetRecord.getVhc22(), sourceRecord.getVhc22()));
        targetRecord.setVhc23(addNullableIntegers(targetRecord.getVhc23(), sourceRecord.getVhc23()));
        targetRecord.setVhc24(addNullableIntegers(targetRecord.getVhc24(), sourceRecord.getVhc24()));
        targetRecord.setVhc25(addNullableIntegers(targetRecord.getVhc25(), sourceRecord.getVhc25()));
        targetRecord.setVhc26(addNullableIntegers(targetRecord.getVhc26(), sourceRecord.getVhc26()));
    }

    /**
     * 复制记录对象
     * @param source 源记录
     * @return 新的记录对象
     */
    private GantryHourFlowWideVO copyRecord(GantryHourFlowWideVO source) {
        GantryHourFlowWideVO target = new GantryHourFlowWideVO();

        // 复制基本属性
        target.setId(source.getId());
        target.setSource(source.getSource());
        target.setGrantryId(source.getGrantryId());
        target.setTime(source.getTime());
        target.setDbCreateTime(source.getDbCreateTime());
        target.setDbUpdateTime(source.getDbUpdateTime());
        target.setPushStatus(source.getPushStatus());
        target.setStartEndPlace(source.getStartEndPlace());
        target.setTimePoint(source.getTimePoint());
        target.setRoadName(source.getRoadName());
        target.setDirection(source.getDirection());
        target.setLon(source.getLon());
        target.setLat(source.getLat());

        // 复制数值字段
        target.setVhc1(source.getVhc1());
        target.setVhc2(source.getVhc2());
        target.setVhc3(source.getVhc3());
        target.setVhc4(source.getVhc4());
        target.setVhc11(source.getVhc11());
        target.setVhc12(source.getVhc12());
        target.setVhc13(source.getVhc13());
        target.setVhc14(source.getVhc14());
        target.setVhc15(source.getVhc15());
        target.setVhc16(source.getVhc16());
        target.setVhc21(source.getVhc21());
        target.setVhc22(source.getVhc22());
        target.setVhc23(source.getVhc23());
        target.setVhc24(source.getVhc24());
        target.setVhc25(source.getVhc25());
        target.setVhc26(source.getVhc26());

        return target;
    }

    /**
     * 安全地累加两个可能为null的Integer值
     * @param a 第一个值
     * @param b 第二个值
     * @return 累加结果，如果都为null则返回null，否则返回非null值或两者之和
     */
    private Integer addNullableIntegers(Integer a, Integer b) {
        if (a == null && b == null) {
            return null;
        }
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        return a + b;
    }
}
